Compare commits
129 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e31051c43 | ||
|
|
683119f322 | ||
|
|
7b1d3e180c | ||
|
|
cc91e95f03 | ||
|
|
5d5b372f44 | ||
|
|
abb41f60f4 | ||
|
|
ec81d67009 | ||
|
|
2a7dc644b7 | ||
|
|
b00a21f39a | ||
|
|
e9396e158b | ||
|
|
7fbcdfeed4 | ||
|
|
f44d885b6d | ||
|
|
6b0a280685 | ||
|
|
78ceec6c6e | ||
|
|
5c56fc5023 | ||
|
|
5a7e54fb9e | ||
|
|
f8f8bf0fea | ||
|
|
6643b6a306 | ||
|
|
7036ab26d7 | ||
|
|
9b55169251 | ||
|
|
ff13c9c186 | ||
|
|
879e7305ca | ||
|
|
1ff827b2ea | ||
|
|
e7f1204fa4 | ||
|
|
9a2c4a34ee | ||
|
|
f4c421f77a | ||
|
|
fe84718b55 | ||
|
|
15d71a01d5 | ||
|
|
abe30f2578 | ||
|
|
fdae48547b | ||
|
|
68ca8df22f | ||
|
|
b8da38f4e4 | ||
|
|
1f103ab7f1 | ||
|
|
da6cf33aac | ||
|
|
73f08b376f | ||
|
|
ed34d1fee7 | ||
|
|
e9f4f1d13c | ||
|
|
e5bb330be5 | ||
|
|
e23e22cb81 | ||
|
|
7434026f5f | ||
|
|
5319d33bc6 | ||
|
|
702311b6b2 | ||
|
|
2511bc20e0 | ||
|
|
ce5a6eabae | ||
|
|
581cd97ba1 | ||
|
|
fa2f99641f | ||
|
|
c40f7db1ab | ||
|
|
be1363e943 | ||
|
|
c313039526 | ||
|
|
73db5dda8c | ||
|
|
5a8fb77fb2 | ||
|
|
4b6ebcbb61 | ||
|
|
bc056c41bc | ||
|
|
5b54442a48 | ||
|
|
dc14cce7a9 | ||
|
|
4f278ba715 | ||
|
|
1036fcca36 | ||
|
|
6b286a5dee | ||
|
|
c8ae675b95 | ||
|
|
4186467129 | ||
|
|
726884afcb | ||
|
|
5a2f3e700b | ||
|
|
911fc74346 | ||
|
|
1388f4d27e | ||
|
|
5b87327a43 | ||
|
|
2fc1679886 | ||
|
|
7ba5652bea | ||
|
|
1e9aebbc86 | ||
|
|
61ec361182 | ||
|
|
7781cbbc57 | ||
|
|
f3b806b471 | ||
|
|
6496405f30 | ||
|
|
85a6dc5e8c | ||
|
|
856bbfc9c8 | ||
|
|
ebaa43fa4c | ||
|
|
2d44b3ebea | ||
|
|
984493db30 | ||
|
|
47848769ff | ||
|
|
a8f6f5b974 | ||
|
|
1e13f474cb | ||
|
|
c69c3a9a46 | ||
|
|
3216b143c2 | ||
|
|
cc963d42a0 | ||
|
|
3f95a62e4f | ||
|
|
7f9a9e2e82 | ||
|
|
375ecd4ada | ||
|
|
8875dccd11 | ||
|
|
4c2301fdf6 | ||
|
|
346594c406 | ||
|
|
2609e2db5c | ||
|
|
692d5b4e08 | ||
|
|
c4af7464e5 | ||
|
|
5a1dc3eb8a | ||
|
|
adcbfcf8d6 | ||
|
|
b57607e7d3 | ||
|
|
2f159d4f45 | ||
|
|
93e1040d07 | ||
|
|
403c07c305 | ||
|
|
6253308e2e | ||
|
|
33a014013a | ||
|
|
4637215ab2 | ||
|
|
ceaedbbd7f | ||
|
|
52f8b1a1d7 | ||
|
|
e6d1250185 | ||
|
|
d04e5e49d0 | ||
|
|
a72436f330 | ||
|
|
467403f437 | ||
|
|
bbaac0c6a9 | ||
|
|
753fd4bda3 | ||
|
|
57d2c8c94a | ||
|
|
870ec89e9a | ||
|
|
0c3b70f2fb | ||
|
|
7a367698fe | ||
|
|
c77e99814b | ||
|
|
4ddd69cc55 | ||
|
|
ef4a61c769 | ||
|
|
7dfb5ff5bd | ||
|
|
6b391312ab | ||
|
|
6e62d77e4d | ||
|
|
0281cca9af | ||
|
|
018e2403b1 | ||
|
|
61f4534e2a | ||
|
|
69667317c1 | ||
|
|
530aac0682 | ||
|
|
6e7d8f90b5 | ||
|
|
65bf1086a2 | ||
|
|
98220442b4 | ||
|
|
3c3d2ef2b9 | ||
|
|
67066eb32a |
357
.gitlab-ci.yml
357
.gitlab-ci.yml
@@ -1,170 +1,88 @@
|
||||
stages:
|
||||
- test
|
||||
- build
|
||||
- package
|
||||
- publish
|
||||
- docs
|
||||
- publish-onchain
|
||||
- optional
|
||||
|
||||
image: parity/rust:gitlab-ci
|
||||
|
||||
variables:
|
||||
GIT_STRATEGY: fetch
|
||||
GIT_SUBMODULE_STRATEGY: recursive
|
||||
CI_SERVER_NAME: "GitLab CI"
|
||||
CARGO_HOME: "${CI_PROJECT_DIR}/cargo"
|
||||
|
||||
BUILD_TARGET: ubuntu
|
||||
BUILD_ARCH: amd64
|
||||
CARGO_HOME: "${CI_PROJECT_DIR}/.cargo"
|
||||
CARGO_TARGET: x86_64-unknown-linux-gnu
|
||||
|
||||
cache:
|
||||
key: "${CI_JOB_NAME}"
|
||||
paths:
|
||||
- ${CI_PROJECT_DIR}/target/
|
||||
- ${CI_PROJECT_DIR}/cargo/
|
||||
|
||||
.releaseable_branches: # list of git refs for building GitLab artifacts (think "pre-release binaries")
|
||||
only: &releaseable_branches
|
||||
- master
|
||||
- stable
|
||||
- beta
|
||||
- tags
|
||||
- schedules
|
||||
|
||||
.publishable_branches: # list of git refs for publishing builds to the "production" locations
|
||||
only: &publishable_branches
|
||||
- nightly # Our nightly builds from schedule, on `master`
|
||||
- "v2*" # Our version tags
|
||||
|
||||
.collect_artifacts: &collect_artifacts
|
||||
artifacts:
|
||||
name: "${CI_JOB_NAME}_${CI_COMMIT_REF_NAME}"
|
||||
name: "${CI_JOB_NAME}_${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}"
|
||||
when: on_success
|
||||
expire_in: 1 mos
|
||||
paths:
|
||||
- artifacts/
|
||||
|
||||
.determine_version:
|
||||
before_script: &determine_version
|
||||
- >
|
||||
VERSION="$(sed -r -n '1,/^version/s/^version = "([^"]+)".*$/\1/p' < Cargo.toml)";
|
||||
if [ "${CI_COMMIT_REF_NAME}" = "nightly" ]; then
|
||||
COMMIT_REF_SHORT="echo ${CI_COMMIT_REF} | grep -oE '^.{7}')";
|
||||
DATE_STRING="$(date +%Y%m%d)";
|
||||
export VERSION="${VERSION}-${COMMIT_REF_SHORT}-${DATE_STRING}";
|
||||
fi;
|
||||
export VERSION;
|
||||
echo "Version: $VERSION"
|
||||
.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: test
|
||||
variables:
|
||||
RUN_TESTS: all
|
||||
script:
|
||||
- scripts/gitlab/test-all.sh
|
||||
- sccache -s
|
||||
tags:
|
||||
- linux-docker
|
||||
|
||||
#### stage: test
|
||||
|
||||
test-rust-stable: &test
|
||||
test-audit:
|
||||
stage: test
|
||||
script:
|
||||
- scripts/gitlab/test.sh stable
|
||||
- set -e
|
||||
- set -u
|
||||
- cargo audit
|
||||
tags:
|
||||
- rust-stable
|
||||
- linux-docker
|
||||
|
||||
.optional_test: &optional_test
|
||||
<<: *test
|
||||
allow_failure: true
|
||||
only:
|
||||
- master
|
||||
|
||||
test-rust-beta:
|
||||
<<: *optional_test
|
||||
script:
|
||||
- scripts/gitlab/test.sh beta
|
||||
|
||||
test-rust-nightly:
|
||||
<<: *optional_test
|
||||
script:
|
||||
- scripts/gitlab/test.sh nightly
|
||||
|
||||
test-lint-rustfmt:
|
||||
<<: *optional_test
|
||||
script:
|
||||
- scripts/gitlab/rustfmt.sh
|
||||
|
||||
test-lint-clippy:
|
||||
<<: *optional_test
|
||||
script:
|
||||
- scripts/gitlab/clippy.sh
|
||||
|
||||
test-coverage-kcov:
|
||||
stage: test
|
||||
only:
|
||||
- master
|
||||
script:
|
||||
- scripts/gitlab/coverage.sh
|
||||
tags:
|
||||
- shell
|
||||
allow_failure: true
|
||||
|
||||
|
||||
#### stage: build
|
||||
|
||||
build-linux-ubuntu-amd64: &build
|
||||
build-linux:
|
||||
stage: build
|
||||
only: *releaseable_branches
|
||||
variables:
|
||||
CARGO_TARGET: x86_64-unknown-linux-gnu
|
||||
script:
|
||||
- scripts/gitlab/build-unix.sh
|
||||
- sccache -s
|
||||
<<: *collect_artifacts
|
||||
tags:
|
||||
- rust-stable
|
||||
allow_failure: true
|
||||
- linux-docker
|
||||
|
||||
build-linux-ubuntu-i386:
|
||||
<<: *build
|
||||
image: parity/rust-i686:gitlab-ci
|
||||
variables:
|
||||
CARGO_TARGET: i686-unknown-linux-gnu
|
||||
tags:
|
||||
- rust-i686
|
||||
|
||||
build-linux-ubuntu-arm64:
|
||||
<<: *build
|
||||
image: parity/rust-arm64:gitlab-ci
|
||||
variables:
|
||||
CARGO_TARGET: aarch64-unknown-linux-gnu
|
||||
tags:
|
||||
- rust-arm
|
||||
|
||||
build-linux-ubuntu-armhf:
|
||||
<<: *build
|
||||
image: parity/rust-armv7:gitlab-ci
|
||||
variables:
|
||||
CARGO_TARGET: armv7-unknown-linux-gnueabihf
|
||||
tags:
|
||||
- rust-arm
|
||||
|
||||
build-linux-android-armhf:
|
||||
<<: *build
|
||||
image: parity/rust-android:gitlab-ci
|
||||
variables:
|
||||
CARGO_TARGET: armv7-linux-androideabi
|
||||
tags:
|
||||
- rust-arm
|
||||
|
||||
build-darwin-macos-x86_64:
|
||||
<<: *build
|
||||
build-darwin:
|
||||
stage: build
|
||||
only: *releaseable_branches
|
||||
variables:
|
||||
CARGO_TARGET: x86_64-apple-darwin
|
||||
CC: gcc
|
||||
CXX: g++
|
||||
script:
|
||||
- scripts/gitlab/build-unix.sh
|
||||
tags:
|
||||
- osx
|
||||
- rust-osx
|
||||
<<: *collect_artifacts
|
||||
|
||||
build-windows-msvc-x86_64:
|
||||
build-windows:
|
||||
stage: build
|
||||
only: *releaseable_branches
|
||||
cache:
|
||||
key: "%CI_JOB_NAME%"
|
||||
paths:
|
||||
- "%CI_PROJECT_DIR%/target/"
|
||||
- "%CI_PROJECT_DIR%/cargo/"
|
||||
# No cargo caching, since fetch-locking on Windows gets stuck
|
||||
variables:
|
||||
CARGO_TARGET: x86_64-pc-windows-msvc
|
||||
script:
|
||||
@@ -173,131 +91,116 @@ build-windows-msvc-x86_64:
|
||||
- rust-windows
|
||||
<<: *collect_artifacts
|
||||
|
||||
|
||||
#### stage: package
|
||||
|
||||
package-linux-snap-amd64: &package_snap
|
||||
stage: package
|
||||
publish-docker:
|
||||
stage: publish
|
||||
only: *releaseable_branches
|
||||
cache: {}
|
||||
before_script: *determine_version
|
||||
variables:
|
||||
CARGO_TARGET: x86_64-unknown-linux-gnu
|
||||
dependencies:
|
||||
- build-linux-ubuntu-amd64
|
||||
script:
|
||||
- scripts/gitlab/package-snap.sh
|
||||
tags:
|
||||
- rust-stable
|
||||
<<: *collect_artifacts
|
||||
|
||||
package-linux-snap-i386:
|
||||
<<: *package_snap
|
||||
variables:
|
||||
BUILD_ARCH: i386
|
||||
CARGO_TARGET: i686-unknown-linux-gnu
|
||||
dependencies:
|
||||
- build-linux-ubuntu-i386
|
||||
|
||||
package-linux-snap-arm64:
|
||||
<<: *package_snap
|
||||
variables:
|
||||
BUILD_ARCH: arm64
|
||||
CARGO_TARGET: aarch64-unknown-linux-gnu
|
||||
dependencies:
|
||||
- build-linux-ubuntu-arm64
|
||||
|
||||
package-linux-snap-armhf:
|
||||
<<: *package_snap
|
||||
variables:
|
||||
BUILD_ARCH: armhf
|
||||
CARGO_TARGET: armv7-unknown-linux-gnueabihf
|
||||
dependencies:
|
||||
- build-linux-ubuntu-armhf
|
||||
|
||||
|
||||
#### stage: publish
|
||||
|
||||
publish-linux-snap-amd64: &publish_snap
|
||||
stage: publish
|
||||
only: *publishable_branches
|
||||
image: snapcore/snapcraft:stable
|
||||
cache: {}
|
||||
before_script: *determine_version
|
||||
variables:
|
||||
BUILD_ARCH: amd64
|
||||
dependencies:
|
||||
- package-linux-snap-amd64
|
||||
script:
|
||||
- scripts/gitlab/publish-snap.sh
|
||||
tags:
|
||||
- rust-stable
|
||||
|
||||
publish-linux-snap-i386:
|
||||
<<: *publish_snap
|
||||
variables:
|
||||
BUILD_ARCH: i386
|
||||
dependencies:
|
||||
- package-linux-snap-i386
|
||||
|
||||
publish-linux-snap-arm64:
|
||||
<<: *publish_snap
|
||||
variables:
|
||||
BUILD_ARCH: arm64
|
||||
dependencies:
|
||||
- package-linux-snap-arm64
|
||||
|
||||
publish-linux-snap-armhf:
|
||||
<<: *publish_snap
|
||||
variables:
|
||||
BUILD_ARCH: armhf
|
||||
dependencies:
|
||||
- package-linux-snap-armhf
|
||||
|
||||
publish-docker-parity-amd64: &publish_docker
|
||||
stage: publish
|
||||
only: *publishable_branches
|
||||
cache: {}
|
||||
dependencies:
|
||||
- build-linux-ubuntu-amd64
|
||||
- build-linux
|
||||
tags:
|
||||
- shell
|
||||
allow_failure: true
|
||||
script:
|
||||
- scripts/gitlab/publish-docker.sh parity
|
||||
|
||||
publish-docker-parityevm-amd64:
|
||||
<<: *publish_docker
|
||||
script:
|
||||
- scripts/gitlab/publish-docker.sh parity-evm
|
||||
|
||||
publish-github-and-s3:
|
||||
stage: publish
|
||||
only: *publishable_branches
|
||||
publish-snap:
|
||||
stage: optional #publish
|
||||
only: *releaseable_branches
|
||||
image: snapcore/snapcraft
|
||||
variables:
|
||||
BUILD_ARCH: amd64
|
||||
cache: {}
|
||||
before_script: *determine_version
|
||||
dependencies:
|
||||
- build-linux-ubuntu-amd64
|
||||
- build-linux-ubuntu-i386
|
||||
- build-linux-ubuntu-armhf
|
||||
- build-linux-ubuntu-arm64
|
||||
- build-darwin-macos-x86_64
|
||||
- build-windows-msvc-x86_64
|
||||
- build-linux
|
||||
tags:
|
||||
- rust-stable
|
||||
script:
|
||||
- scripts/gitlab/publish-snap.sh
|
||||
allow_failure: true
|
||||
<<: *collect_artifacts
|
||||
|
||||
publish-onnet-update:
|
||||
stage: publish-onchain
|
||||
only: *releaseable_branches
|
||||
cache: {}
|
||||
dependencies:
|
||||
- build-linux
|
||||
- build-darwin
|
||||
- build-windows
|
||||
- publish-awss3-release
|
||||
before_script: *determine_version
|
||||
script:
|
||||
- scripts/gitlab/push.sh
|
||||
- scripts/gitlab/publish-onnet-update.sh
|
||||
tags:
|
||||
- shell
|
||||
allow_failure: true
|
||||
- linux-docker
|
||||
|
||||
# configures aws for fast uploads/syncs
|
||||
.s3-before-script: &s3-before-script
|
||||
before_script:
|
||||
- mkdir -p ${HOME}/.aws
|
||||
- |
|
||||
cat > ${HOME}/.aws/config <<EOC
|
||||
[default]
|
||||
s3 =
|
||||
max_concurrent_requests = 20
|
||||
max_queue_size = 10000
|
||||
multipart_threshold = 64MB
|
||||
multipart_chunksize = 16MB
|
||||
max_bandwidth = 50MB/s
|
||||
use_accelerate_endpoint = false
|
||||
addressing_style = path
|
||||
EOC
|
||||
|
||||
####stage: docs
|
||||
publish-awss3-release:
|
||||
image: parity/awscli:latest
|
||||
stage: publish
|
||||
only: *releaseable_branches
|
||||
cache: {}
|
||||
dependencies:
|
||||
- build-linux
|
||||
- build-darwin
|
||||
- build-windows
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
<<: *s3-before-script
|
||||
script:
|
||||
- echo "__________Push binaries to AWS S3____________"
|
||||
- case "${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}" in
|
||||
(beta|stable|nightly)
|
||||
export BUCKET=releases.parity.io/ethereum;
|
||||
;;
|
||||
(*)
|
||||
export BUCKET=builds-parity;
|
||||
;;
|
||||
esac
|
||||
- aws s3 sync ./artifacts s3://${BUCKET}/${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}/
|
||||
after_script:
|
||||
- aws s3 ls s3://${BUCKET}/${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}/
|
||||
--recursive --human-readable --summarize
|
||||
tags:
|
||||
- linux-docker
|
||||
|
||||
docs-rpc-json:
|
||||
stage: docs
|
||||
publish-docs:
|
||||
stage: publish
|
||||
only:
|
||||
- tags
|
||||
except:
|
||||
- nightly
|
||||
cache: {}
|
||||
script:
|
||||
- scripts/gitlab/rpc-docs.sh
|
||||
- scripts/gitlab/publish-docs.sh
|
||||
tags:
|
||||
- shell
|
||||
- linux-docker
|
||||
|
||||
build-android:
|
||||
stage: optional
|
||||
image: parity/rust-android:gitlab-ci
|
||||
variables:
|
||||
CARGO_TARGET: armv7-linux-androideabi
|
||||
script:
|
||||
- scripts/gitlab/build-unix.sh
|
||||
tags:
|
||||
- linux-docker
|
||||
allow_failure: true
|
||||
<<: *collect_artifacts
|
||||
|
||||
|
||||
1190
CHANGELOG.md
1190
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
2056
Cargo.lock
generated
2056
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
14
Cargo.toml
14
Cargo.toml
@@ -2,7 +2,7 @@
|
||||
description = "Parity Ethereum client"
|
||||
name = "parity-ethereum"
|
||||
# NOTE Make sure to update util/version/Cargo.toml as well
|
||||
version = "2.1.0"
|
||||
version = "2.2.11"
|
||||
license = "GPL-3.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
@@ -28,10 +28,9 @@ serde = "1.0"
|
||||
serde_json = "1.0"
|
||||
serde_derive = "1.0"
|
||||
futures = "0.1"
|
||||
futures-cpupool = "0.1"
|
||||
fdlimit = "0.1"
|
||||
ctrlc = { git = "https://github.com/paritytech/rust-ctrlc.git" }
|
||||
jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.11" }
|
||||
jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-2.2" }
|
||||
ethcore = { path = "ethcore", features = ["parity"] }
|
||||
parity-bytes = "0.1"
|
||||
ethcore-io = { path = "util/io" }
|
||||
@@ -46,12 +45,12 @@ ethcore-transaction = { path = "ethcore/transaction" }
|
||||
ethereum-types = "0.4"
|
||||
node-filter = { path = "ethcore/node_filter" }
|
||||
ethkey = { path = "ethkey" }
|
||||
rlp = { version = "0.2.4", features = ["ethereum"] }
|
||||
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 = "local-store" }
|
||||
parity-reactor = { path = "util/reactor" }
|
||||
parity-runtime = { path = "util/runtime" }
|
||||
parity-rpc = { path = "rpc" }
|
||||
parity-rpc-client = { path = "rpc_client" }
|
||||
parity-updater = { path = "updater" }
|
||||
@@ -84,11 +83,12 @@ fake-fetch = { path = "util/fake-fetch" }
|
||||
winapi = { version = "0.3.4", features = ["winsock2", "winuser", "shellapi"] }
|
||||
|
||||
[target.'cfg(not(windows))'.dependencies]
|
||||
daemonize = { git = "https://github.com/paritytech/daemonize" }
|
||||
daemonize = "0.3"
|
||||
|
||||
[features]
|
||||
miner-debug = ["ethcore/miner-debug"]
|
||||
json-tests = ["ethcore/json-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"]
|
||||
@@ -139,4 +139,4 @@ members = [
|
||||
]
|
||||
|
||||
[patch.crates-io]
|
||||
ring = { git = "https://github.com/paritytech/ring" }
|
||||
heapsize = { git = "https://github.com/cheme/heapsize.git", branch = "ec-macfix" }
|
||||
|
||||
28
README.md
28
README.md
@@ -4,9 +4,7 @@
|
||||
|
||||
<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/commits/master" target="_blank"><img src="https://gitlab.parity.io/parity/parity/badges/master/build.svg" /></a>
|
||||
<a href="https://codecov.io/gh/paritytech/parity-ethereum" target="_blank"><img src="https://codecov.io/gh/paritytech/parity-ethereum/branch/master/graph/badge.svg" /></a>
|
||||
<a href="https://build.snapcraft.io/user/paritytech/parity" target="_blank"><img src="https://build.snapcraft.io/badge/paritytech/parity.svg" /></a>
|
||||
<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>
|
||||
|
||||
**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.
|
||||
@@ -25,11 +23,11 @@ By default, Parity Ethereum runs a JSON-RPC HTTP server on port `:8545` and a We
|
||||
|
||||
If you run into problems while using Parity Ethereum, check out the [wiki for documentation](https://wiki.parity.io/), feel free to [file an issue in this repository](https://github.com/paritytech/parity-ethereum/issues/new), or hop on our [Gitter](https://gitter.im/paritytech/parity) or [Riot](https://riot.im/app/#/group/+parity:matrix.parity.io) chat room to ask a question. We are glad to help! **For security-critical issues**, please refer to the security policy outlined in [SECURITY.md](SECURITY.md).
|
||||
|
||||
Parity Ethereum's current beta-release is 2.0. 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.
|
||||
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.
|
||||
|
||||
## Build Dependencies
|
||||
|
||||
Parity Ethereum requires **Rust version 1.28.x** 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:
|
||||
|
||||
@@ -60,26 +58,6 @@ 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.
|
||||
|
||||
## Install from the Snapcraft Store
|
||||
|
||||
In any of the [supported Linux distros](https://snapcraft.io/docs/core/install):
|
||||
|
||||
```bash
|
||||
sudo snap install parity
|
||||
```
|
||||
|
||||
Alternatively, if you want to contribute testing the upcoming release:
|
||||
|
||||
```bash
|
||||
sudo snap install parity --beta
|
||||
```
|
||||
|
||||
Moreover, to test the latest code from the master branch:
|
||||
|
||||
```bash
|
||||
sudo snap install parity --edge
|
||||
```
|
||||
|
||||
## Build from Source Code
|
||||
|
||||
```bash
|
||||
|
||||
@@ -6,4 +6,3 @@ authors = ["Marek Kotewicz <marek@parity.io>"]
|
||||
[dependencies]
|
||||
ethjson = { path = "../json" }
|
||||
serde_json = "1.0"
|
||||
serde_ignored = "0.0.4"
|
||||
|
||||
@@ -15,10 +15,8 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
extern crate serde_json;
|
||||
extern crate serde_ignored;
|
||||
extern crate ethjson;
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
use std::{fs, env, process};
|
||||
use ethjson::spec::Spec;
|
||||
|
||||
@@ -41,24 +39,11 @@ fn main() {
|
||||
Err(_) => quit(&format!("{} could not be opened", path)),
|
||||
};
|
||||
|
||||
let mut unused = BTreeSet::new();
|
||||
let mut deserializer = serde_json::Deserializer::from_reader(file);
|
||||
|
||||
let spec: Result<Spec, _> = serde_ignored::deserialize(&mut deserializer, |field| {
|
||||
unused.insert(field.to_string());
|
||||
});
|
||||
let spec: Result<Spec, _> = serde_json::from_reader(file);
|
||||
|
||||
if let Err(err) = spec {
|
||||
quit(&format!("{} {}", path, err.to_string()));
|
||||
}
|
||||
|
||||
if !unused.is_empty() {
|
||||
let err = unused.into_iter()
|
||||
.map(|field| format!("{} unexpected field `{}`", path, field))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
quit(&err);
|
||||
}
|
||||
|
||||
println!("{} is valid", path);
|
||||
}
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
FROM ubuntu:xenial
|
||||
LABEL maintainer="Parity Technologies <devops@parity.io>"
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -yq sudo curl file build-essential wget git g++ cmake pkg-config bison flex \
|
||||
unzip lib32stdc++6 lib32z1 python autotools-dev automake autoconf libtool \
|
||||
gperf xsltproc docbook-xsl
|
||||
|
||||
# Rust & Cargo
|
||||
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y
|
||||
ENV PATH /root/.cargo/bin:$PATH
|
||||
RUN rustup toolchain install stable
|
||||
RUN rustup target add --toolchain stable arm-linux-androideabi
|
||||
RUN rustup target add --toolchain stable armv7-linux-androideabi
|
||||
|
||||
# Android NDK and toolchain
|
||||
RUN cd /usr/local && \
|
||||
wget -q https://dl.google.com/android/repository/android-ndk-r16b-linux-x86_64.zip && \
|
||||
unzip -q android-ndk-r16b-linux-x86_64.zip && \
|
||||
rm android-ndk-r16b-linux-x86_64.zip
|
||||
ENV NDK_HOME /usr/local/android-ndk-r16b
|
||||
RUN /usr/local/android-ndk-r16b/build/tools/make-standalone-toolchain.sh \
|
||||
--arch=arm --install-dir=/opt/ndk-standalone --stl=libc++ --platform=android-26
|
||||
ENV PATH $PATH:/opt/ndk-standalone/bin
|
||||
|
||||
# Compiling libudev for Android
|
||||
# This is the most hacky part of the process, as we need to apply a patch and pass specific
|
||||
# options that the compiler environment doesn't define.
|
||||
RUN cd /root && \
|
||||
git clone https://github.com/gentoo/eudev.git
|
||||
ADD libudev.patch /root
|
||||
RUN cd /root/eudev && \
|
||||
git checkout 83d918449f22720d84a341a05e24b6d109e6d3ae && \
|
||||
./autogen.sh && \
|
||||
./configure --disable-introspection --disable-programs --disable-hwdb \
|
||||
--host=arm-linux-androideabi --prefix=/opt/ndk-standalone/sysroot/usr/ \
|
||||
--enable-shared=false CC=arm-linux-androideabi-clang \
|
||||
CFLAGS="-D LINE_MAX=2048 -D RLIMIT_NLIMITS=15 -D IPTOS_LOWCOST=2 -std=gnu99" \
|
||||
CXX=arm-linux-androideabi-clang++ && \
|
||||
git apply - < /root/libudev.patch && \
|
||||
make && \
|
||||
make install
|
||||
RUN rm -rf /root/eudev
|
||||
RUN rm /root/libudev.patch
|
||||
|
||||
# Rust-related configuration
|
||||
ADD cargo-config.toml /root/.cargo/config
|
||||
ENV ARM_LINUX_ANDROIDEABI_OPENSSL_DIR /opt/ndk-standalone/sysroot/usr
|
||||
ENV ARMV7_LINUX_ANDROIDEABI_OPENSSL_DIR /opt/ndk-standalone/sysroot/usr
|
||||
ENV CC_arm_linux_androideabi arm-linux-androideabi-clang
|
||||
ENV CC_armv7_linux_androideabi arm-linux-androideabi-clang
|
||||
ENV CXX_arm_linux_androideabi arm-linux-androideabi-clang++
|
||||
ENV CXX_armv7_linux_androideabi arm-linux-androideabi-clang++
|
||||
ENV AR_arm_linux_androideabi arm-linux-androideabi-ar
|
||||
ENV AR_armv7_linux_androideabi arm-linux-androideabi-ar
|
||||
ENV CFLAGS_arm_linux_androideabi -std=gnu11 -fPIC -D OS_ANDROID
|
||||
ENV CFLAGS_armv7_linux_androideabi -std=gnu11 -fPIC -D OS_ANDROID
|
||||
ENV CXXFLAGS_arm_linux_androideabi -std=gnu++11 -fPIC -fexceptions -frtti -static-libstdc++ -D OS_ANDROID
|
||||
ENV CXXFLAGS_armv7_linux_androideabi -std=gnu++11 -fPIC -fexceptions -frtti -static-libstdc++ -D OS_ANDROID
|
||||
ENV CXXSTDLIB_arm_linux_androideabi ""
|
||||
ENV CXXSTDLIB_armv7_linux_androideabi ""
|
||||
@@ -1,9 +0,0 @@
|
||||
[target.armv7-linux-androideabi]
|
||||
linker = "arm-linux-androideabi-clang"
|
||||
ar = "arm-linux-androideabi-ar"
|
||||
rustflags = ["-C", "link-arg=-lc++_static", "-C", "link-arg=-lc++abi", "-C", "link-arg=-landroid_support"]
|
||||
|
||||
[target.arm-linux-androideabi]
|
||||
linker = "arm-linux-androideabi-clang"
|
||||
ar = "arm-linux-androideabi-ar"
|
||||
rustflags = ["-C", "link-arg=-lc++_static", "-C", "link-arg=-lc++abi", "-C", "link-arg=-landroid_support"]
|
||||
@@ -1,216 +0,0 @@
|
||||
diff --git a/src/collect/collect.c b/src/collect/collect.c
|
||||
index 2cf1f00..b24f26b 100644
|
||||
--- a/src/collect/collect.c
|
||||
+++ b/src/collect/collect.c
|
||||
@@ -84,7 +84,7 @@ static void usage(void)
|
||||
" invoked for each ID in <idlist>) collect returns 0, the\n"
|
||||
" number of missing IDs otherwise.\n"
|
||||
" On error a negative number is returned.\n\n"
|
||||
- , program_invocation_short_name);
|
||||
+ , "parity");
|
||||
}
|
||||
|
||||
/*
|
||||
diff --git a/src/scsi_id/scsi_id.c b/src/scsi_id/scsi_id.c
|
||||
index 8b76d87..7bf3948 100644
|
||||
--- a/src/scsi_id/scsi_id.c
|
||||
+++ b/src/scsi_id/scsi_id.c
|
||||
@@ -321,7 +321,7 @@ static void help(void) {
|
||||
" -u --replace-whitespace Replace all whitespace by underscores\n"
|
||||
" -v --verbose Verbose logging\n"
|
||||
" -x --export Print values as environment keys\n"
|
||||
- , program_invocation_short_name);
|
||||
+ , "parity");
|
||||
|
||||
}
|
||||
|
||||
diff --git a/src/shared/hashmap.h b/src/shared/hashmap.h
|
||||
index a03ee58..a7c2005 100644
|
||||
--- a/src/shared/hashmap.h
|
||||
+++ b/src/shared/hashmap.h
|
||||
@@ -98,10 +98,7 @@ extern const struct hash_ops uint64_hash_ops;
|
||||
#if SIZEOF_DEV_T != 8
|
||||
unsigned long devt_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) _pure_;
|
||||
int devt_compare_func(const void *a, const void *b) _pure_;
|
||||
-extern const struct hash_ops devt_hash_ops = {
|
||||
- .hash = devt_hash_func,
|
||||
- .compare = devt_compare_func
|
||||
-};
|
||||
+extern const struct hash_ops devt_hash_ops;
|
||||
#else
|
||||
#define devt_hash_func uint64_hash_func
|
||||
#define devt_compare_func uint64_compare_func
|
||||
diff --git a/src/shared/log.c b/src/shared/log.c
|
||||
index 4a40996..1496984 100644
|
||||
--- a/src/shared/log.c
|
||||
+++ b/src/shared/log.c
|
||||
@@ -335,7 +335,7 @@ static int write_to_syslog(
|
||||
|
||||
IOVEC_SET_STRING(iovec[0], header_priority);
|
||||
IOVEC_SET_STRING(iovec[1], header_time);
|
||||
- IOVEC_SET_STRING(iovec[2], program_invocation_short_name);
|
||||
+ IOVEC_SET_STRING(iovec[2], "parity");
|
||||
IOVEC_SET_STRING(iovec[3], header_pid);
|
||||
IOVEC_SET_STRING(iovec[4], buffer);
|
||||
|
||||
@@ -383,7 +383,7 @@ static int write_to_kmsg(
|
||||
char_array_0(header_pid);
|
||||
|
||||
IOVEC_SET_STRING(iovec[0], header_priority);
|
||||
- IOVEC_SET_STRING(iovec[1], program_invocation_short_name);
|
||||
+ IOVEC_SET_STRING(iovec[1], "parity");
|
||||
IOVEC_SET_STRING(iovec[2], header_pid);
|
||||
IOVEC_SET_STRING(iovec[3], buffer);
|
||||
IOVEC_SET_STRING(iovec[4], "\n");
|
||||
diff --git a/src/udev/udevadm-control.c b/src/udev/udevadm-control.c
|
||||
index 6af7163..3271e56 100644
|
||||
--- a/src/udev/udevadm-control.c
|
||||
+++ b/src/udev/udevadm-control.c
|
||||
@@ -41,7 +41,7 @@ static void print_help(void) {
|
||||
" -p --property=KEY=VALUE Set a global property for all events\n"
|
||||
" -m --children-max=N Maximum number of children\n"
|
||||
" --timeout=SECONDS Maximum time to block for a reply\n"
|
||||
- , program_invocation_short_name);
|
||||
+ , "parity");
|
||||
}
|
||||
|
||||
static int adm_control(struct udev *udev, int argc, char *argv[]) {
|
||||
diff --git a/src/udev/udevadm-info.c b/src/udev/udevadm-info.c
|
||||
index 0aec976..a31ac02 100644
|
||||
--- a/src/udev/udevadm-info.c
|
||||
+++ b/src/udev/udevadm-info.c
|
||||
@@ -279,7 +279,7 @@ static void help(void) {
|
||||
" -P --export-prefix Export the key name with a prefix\n"
|
||||
" -e --export-db Export the content of the udev database\n"
|
||||
" -c --cleanup-db Clean up the udev database\n"
|
||||
- , program_invocation_short_name);
|
||||
+ , "parity");
|
||||
}
|
||||
|
||||
static int uinfo(struct udev *udev, int argc, char *argv[]) {
|
||||
diff --git a/src/udev/udevadm-monitor.c b/src/udev/udevadm-monitor.c
|
||||
index 15ded09..b58dd08 100644
|
||||
--- a/src/udev/udevadm-monitor.c
|
||||
+++ b/src/udev/udevadm-monitor.c
|
||||
@@ -73,7 +73,7 @@ static void help(void) {
|
||||
" -u --udev Print udev events\n"
|
||||
" -s --subsystem-match=SUBSYSTEM[/DEVTYPE] Filter events by subsystem\n"
|
||||
" -t --tag-match=TAG Filter events by tag\n"
|
||||
- , program_invocation_short_name);
|
||||
+ , "parity");
|
||||
}
|
||||
|
||||
static int adm_monitor(struct udev *udev, int argc, char *argv[]) {
|
||||
diff --git a/src/udev/udevadm-settle.c b/src/udev/udevadm-settle.c
|
||||
index 33597bc..b36a504 100644
|
||||
--- a/src/udev/udevadm-settle.c
|
||||
+++ b/src/udev/udevadm-settle.c
|
||||
@@ -43,7 +43,7 @@ static void help(void) {
|
||||
" --version Show package version\n"
|
||||
" -t --timeout=SECONDS Maximum time to wait for events\n"
|
||||
" -E --exit-if-exists=FILE Stop waiting if file exists\n"
|
||||
- , program_invocation_short_name);
|
||||
+ , "parity");
|
||||
}
|
||||
|
||||
static int adm_settle(struct udev *udev, int argc, char *argv[]) {
|
||||
diff --git a/src/udev/udevadm-test-builtin.c b/src/udev/udevadm-test-builtin.c
|
||||
index baaeca9..50ed812 100644
|
||||
--- a/src/udev/udevadm-test-builtin.c
|
||||
+++ b/src/udev/udevadm-test-builtin.c
|
||||
@@ -39,7 +39,7 @@ static void help(struct udev *udev) {
|
||||
" -h --help Print this message\n"
|
||||
" --version Print version of the program\n\n"
|
||||
"Commands:\n"
|
||||
- , program_invocation_short_name);
|
||||
+ , "parity");
|
||||
|
||||
udev_builtin_list(udev);
|
||||
}
|
||||
diff --git a/src/udev/udevadm-test.c b/src/udev/udevadm-test.c
|
||||
index 47fd924..a855412 100644
|
||||
--- a/src/udev/udevadm-test.c
|
||||
+++ b/src/udev/udevadm-test.c
|
||||
@@ -39,7 +39,7 @@ static void help(void) {
|
||||
" --version Show package version\n"
|
||||
" -a --action=ACTION Set action string\n"
|
||||
" -N --resolve-names=early|late|never When to resolve names\n"
|
||||
- , program_invocation_short_name);
|
||||
+ , "parity");
|
||||
}
|
||||
|
||||
static int adm_test(struct udev *udev, int argc, char *argv[]) {
|
||||
diff --git a/src/udev/udevadm-trigger.c b/src/udev/udevadm-trigger.c
|
||||
index 4dc756a..67787d3 100644
|
||||
--- a/src/udev/udevadm-trigger.c
|
||||
+++ b/src/udev/udevadm-trigger.c
|
||||
@@ -92,7 +92,7 @@ static void help(void) {
|
||||
" -y --sysname-match=NAME Trigger devices with this /sys path\n"
|
||||
" --name-match=NAME Trigger devices with this /dev name\n"
|
||||
" -b --parent-match=NAME Trigger devices with that parent device\n"
|
||||
- , program_invocation_short_name);
|
||||
+ , "parity");
|
||||
}
|
||||
|
||||
static int adm_trigger(struct udev *udev, int argc, char *argv[]) {
|
||||
diff --git a/src/udev/udevadm.c b/src/udev/udevadm.c
|
||||
index 3e57cf6..b03dfaa 100644
|
||||
--- a/src/udev/udevadm.c
|
||||
+++ b/src/udev/udevadm.c
|
||||
@@ -62,7 +62,7 @@ static int adm_help(struct udev *udev, int argc, char *argv[]) {
|
||||
printf("%s [--help] [--version] [--debug] COMMAND [COMMAND OPTIONS]\n\n"
|
||||
"Send control commands or test the device manager.\n\n"
|
||||
"Commands:\n"
|
||||
- , program_invocation_short_name);
|
||||
+ , "parity");
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(udevadm_cmds); i++)
|
||||
if (udevadm_cmds[i]->help != NULL)
|
||||
@@ -128,7 +128,7 @@ int main(int argc, char *argv[]) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
- fprintf(stderr, "%s: missing or unknown command\n", program_invocation_short_name);
|
||||
+ fprintf(stderr, "%s: missing or unknown command\n", "parity");
|
||||
rc = 2;
|
||||
out:
|
||||
mac_selinux_finish();
|
||||
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
|
||||
index cf826c6..4eec0af 100644
|
||||
--- a/src/udev/udevd.c
|
||||
+++ b/src/udev/udevd.c
|
||||
@@ -1041,7 +1041,7 @@ static void help(void) {
|
||||
" -t --event-timeout=SECONDS Seconds to wait before terminating an event\n"
|
||||
" -N --resolve-names=early|late|never\n"
|
||||
" When to resolve users and groups\n"
|
||||
- , program_invocation_short_name);
|
||||
+ , "parity");
|
||||
}
|
||||
|
||||
static int parse_argv(int argc, char *argv[]) {
|
||||
diff --git a/src/v4l_id/v4l_id.c b/src/v4l_id/v4l_id.c
|
||||
index 1dce0d5..f65badf 100644
|
||||
--- a/src/v4l_id/v4l_id.c
|
||||
+++ b/src/v4l_id/v4l_id.c
|
||||
@@ -49,7 +49,7 @@ int main(int argc, char *argv[]) {
|
||||
printf("%s [-h,--help] <device file>\n\n"
|
||||
"Video4Linux device identification.\n\n"
|
||||
" -h Print this message\n"
|
||||
- , program_invocation_short_name);
|
||||
+ , "parity");
|
||||
return 0;
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
diff --git a/src/shared/path-util.c b/src/shared/path-util.c
|
||||
index 0744563..7151356 100644
|
||||
--- a/src/shared/path-util.c
|
||||
+++ b/src/shared/path-util.c
|
||||
@@ -109,7 +109,7 @@ char *path_make_absolute_cwd(const char *p) {
|
||||
if (path_is_absolute(p))
|
||||
return strdup(p);
|
||||
|
||||
- cwd = get_current_dir_name();
|
||||
+ cwd = getcwd(malloc(128), 128);
|
||||
if (!cwd)
|
||||
return NULL;
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
FROM ubuntu:xenial
|
||||
MAINTAINER Parity Technologies <devops@parity.io>
|
||||
#set ENVIROMENT
|
||||
ARG TARGET
|
||||
ENV TARGET ${TARGET}
|
||||
|
||||
# install tools and dependencies
|
||||
RUN apt update && apt install -y --no-install-recommends openssl libudev-dev file
|
||||
|
||||
# show backtraces
|
||||
ENV RUST_BACKTRACE 1
|
||||
|
||||
#cleanup Docker image
|
||||
RUN apt autoremove -y
|
||||
RUN apt clean -y
|
||||
RUN rm -rf /tmp/* /var/tmp/* /var/lib/apt/lists/*
|
||||
|
||||
#add TARGET to docker image
|
||||
COPY artifacts/x86_64-unknown-linux-gnu/$TARGET /usr/bin/$TARGET
|
||||
|
||||
# Build a shell script because the ENTRYPOINT command doesn't like using ENV
|
||||
RUN echo "#!/bin/bash \n ${TARGET} \$@" > ./entrypoint.sh
|
||||
RUN chmod +x ./entrypoint.sh
|
||||
|
||||
# setup ENTRYPOINT
|
||||
EXPOSE 5001 8080 8082 8083 8545 8546 8180 30303/tcp 30303/udp
|
||||
ENTRYPOINT ["./entrypoint.sh"]
|
||||
@@ -1,45 +0,0 @@
|
||||
FROM ubuntu:14.04
|
||||
WORKDIR /build
|
||||
|
||||
# install tools and dependencies
|
||||
RUN apt-get -y update && \
|
||||
apt-get install -y --force-yes --no-install-recommends \
|
||||
curl git make g++ gcc-aarch64-linux-gnu g++-aarch64-linux-gnu \
|
||||
libc6-arm64-cross libc6-dev-arm64-cross wget file ca-certificates \
|
||||
binutils-aarch64-linux-gnu cmake3 libudev-dev \
|
||||
&& \
|
||||
apt-get clean
|
||||
|
||||
# install rustup
|
||||
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y
|
||||
|
||||
# rustup directory
|
||||
ENV PATH /root/.cargo/bin:$PATH
|
||||
|
||||
ENV RUST_TARGETS="aarch64-unknown-linux-gnu"
|
||||
|
||||
# multirust add arm--linux-gnuabhf toolchain
|
||||
RUN rustup target add aarch64-unknown-linux-gnu
|
||||
|
||||
# show backtraces
|
||||
ENV RUST_BACKTRACE 1
|
||||
|
||||
# show tools
|
||||
RUN rustc -vV && cargo -V
|
||||
|
||||
# build parity
|
||||
ADD . /build/parity
|
||||
RUN cd parity && \
|
||||
mkdir -p .cargo && \
|
||||
echo '[target.aarch64-unknown-linux-gnu]\n\
|
||||
linker = "aarch64-linux-gnu-gcc"\n'\
|
||||
>>.cargo/config && \
|
||||
cat .cargo/config && \
|
||||
cargo build --target aarch64-unknown-linux-gnu --release --verbose && \
|
||||
ls /build/parity/target/aarch64-unknown-linux-gnu/release/parity && \
|
||||
/usr/bin/aarch64-linux-gnu-strip /build/parity/target/aarch64-unknown-linux-gnu/release/parity
|
||||
|
||||
RUN file /build/parity/target/aarch64-unknown-linux-gnu/release/parity
|
||||
|
||||
EXPOSE 8080 8545 8180
|
||||
ENTRYPOINT ["/build/parity/target/aarch64-unknown-linux-gnu/release/parity"]
|
||||
@@ -1,4 +1,84 @@
|
||||
## Parity [v1.11.8](https://github.com/paritytech/parity-ethereum/releases/tag/v1.11.8) (2018-07-27)
|
||||
Note: Parity 1.11 reached End-of-Life on 2018-09-19 (EOL).
|
||||
|
||||
## Parity-Ethereum [v1.11.11](https://github.com/paritytech/parity-ethereum/releases/tag/v1.11.11) (2018-09-11)
|
||||
|
||||
Parity-Ethereum 1.11.11-stable is a bug-fix release to improve performance and stability.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
- Stable backports 1.11.11 ([#9443](https://github.com/paritytech/parity-ethereum/pull/9443))
|
||||
- Parity-version: bump stable to 1.11.11
|
||||
- Update tobalaba.json ([#9419](https://github.com/paritytech/parity-ethereum/pull/9419))
|
||||
- Update hardcoded sync ([#9421](https://github.com/paritytech/parity-ethereum/pull/9421))
|
||||
- Update foundation hardcoded header to block 6219777
|
||||
- Update ropsten hardcoded header to block 3917825
|
||||
- Update kovan hardcoded header to block 8511489
|
||||
- Parity: print correct keys path on startup ([#9501](https://github.com/paritytech/parity-ethereum/pull/9501))
|
||||
- Only check warp syncing for eth_getWorks ([#9484](https://github.com/paritytech/parity-ethereum/pull/9484))
|
||||
- Only check warp syncing for eth_getWorks
|
||||
- Use SyncStatus::is_snapshot_syncing
|
||||
|
||||
## Parity-Ethereum [v1.11.10](https://github.com/paritytech/parity-ethereum/releases/tag/v1.11.10) (2018-08-31)
|
||||
|
||||
Parity-Ethereum 1.11.10-stable is a bug-fix release to improve performance and stability.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
- Stable backports for 1.11.10 ([#9228](https://github.com/paritytech/parity-ethereum/pull/9228))
|
||||
- Parity-version: bump stable to 1.11.9
|
||||
- Fix compilation error on nightly rust ([#8707](https://github.com/paritytech/parity-ethereum/pull/8707))
|
||||
- On nightly rust passing `public_url` works but that breaks on stable. This works for both.
|
||||
- Parity-version: bump stable to 1.11.10
|
||||
- Check if synced when using eth_getWork ([#9193](https://github.com/paritytech/parity-ethereum/issues/9193)) ([#9210](https://github.com/paritytech/parity-ethereum/pull/9210))
|
||||
- Check if synced when using eth_getWork ([#9193](https://github.com/paritytech/parity-ethereum/issues/9193))
|
||||
- Don't use fn syncing
|
||||
- Fix identation
|
||||
- Fix typo
|
||||
- Don't check for warping
|
||||
- Rpc: avoid calling queue_info twice on eth_getWork
|
||||
- Fix potential as_usize overflow when casting from U256 in miner ([#9221](https://github.com/paritytech/parity-ethereum/pull/9221))
|
||||
- Allow old blocks from peers with lower difficulty ([#9226](https://github.com/paritytech/parity-ethereum/pull/9226))
|
||||
- Previously we only allow downloading of old blocks if the peer difficulty was greater than our syncing difficulty. This change allows downloading of blocks from peers where the difficulty is greater then the last downloaded old block.
|
||||
- Update Dockerfile ([#9242](https://github.com/paritytech/parity-ethereum/pull/9242))
|
||||
- Update Dockerfile
|
||||
- Fix Docker build
|
||||
- Fix dockerfile paths: parity -> parity-ethereum ([#9248](https://github.com/paritytech/parity-ethereum/pull/9248))
|
||||
- Update tobalaba.json ([#9313](https://github.com/paritytech/parity-ethereum/pull/9313))
|
||||
- Light client `Provide default nonce in transactions when it´s missing` ([#9370](https://github.com/paritytech/parity-ethereum/pull/9370))
|
||||
- Provide `default_nonce` in tx`s when it´s missing
|
||||
- When `nonce` is missing in a `EthTransaction` will cause it to fall in these cases provide `default_nonce` value instead!
|
||||
- Changed http:// to https:// on Yasm link ([#9369](https://github.com/paritytech/parity-ethereum/pull/9369))
|
||||
- Changed http:// to https:// on Yasm link in README.md
|
||||
- Provide `default_nonce` in tx`s when it´s missing
|
||||
- When `nonce` is missing in a `EthTransaction` will cause it to fall in these cases provide `default_nonce` value instead!
|
||||
- Address grumbles
|
||||
- Ethcore: kovan: delay activation of strict score validation ([#9406](https://github.com/paritytech/parity-ethereum/pull/9406))
|
||||
- Use impl Future in the light client RPC helpers ([#8628](https://github.com/paritytech/parity-ethereum/pull/8628))
|
||||
- Better support for eth_getLogs in light mode ([#9186](https://github.com/paritytech/parity-ethereum/pull/9186))
|
||||
- Light client on-demand request for headers range.
|
||||
- Cache headers in HeaderWithAncestors response.
|
||||
- Also fulfills request locally if all headers are in cache.
|
||||
- Lightfetch::logs fetches missing headers on demand.
|
||||
- Lightfetch::logs limit the number of headers requested at a time.
|
||||
- Lightfetch::logs refactor header fetching logic.
|
||||
- Enforce limit on header range length in light client logs request.
|
||||
- Fix light request tests after struct change.
|
||||
- Respond to review comments.
|
||||
- Propagate transactions for next 4 blocks. ([#9265](https://github.com/paritytech/parity-ethereum/pull/9265))
|
||||
- This PR also removes the limit of max 64 transactions per packet, currently we only attempt to prevent the packet size to go over 8MB. This will only be the case for super-large transactions or high-block-gas-limit chains.
|
||||
- Patching this is important only for chains that have blocks that can fit more than 4k transactions (over 86M block gas limit)
|
||||
- For mainnet, we should actually see a tiny bit faster propagation since instead of computing 4k pending set, we only need `4 * 8M / 21k = 1523` transactions.
|
||||
- Ethcore: fix pow difficulty validation ([#9328](https://github.com/paritytech/parity-ethereum/pull/9328))
|
||||
- Ethcore: fix pow difficulty validation
|
||||
- Ethcore: validate difficulty is not zero
|
||||
- Ethcore: add issue link to regression test
|
||||
- Ethcore: fix tests
|
||||
- Ethcore: move difficulty_to_boundary to ethash crate
|
||||
- Ethcore: reuse difficulty_to_boundary and boundary_to_difficulty
|
||||
- Ethcore: fix grumbles in difficulty_to_boundary_aux
|
||||
- Add snapcraft cmake build dependency ([#9243](https://github.com/paritytech/parity-ethereum/pull/9243))
|
||||
|
||||
## Parity-Ethereum [v1.11.8](https://github.com/paritytech/parity-ethereum/releases/tag/v1.11.8) (2018-07-27)
|
||||
|
||||
Parity 1.11.8-stable is a bug-fix release to improve performance and stability.
|
||||
|
||||
@@ -42,7 +122,7 @@ The full list of included changes:
|
||||
- Ethcore: update to parity-wasm 0.31
|
||||
- Rpc: fix broken merge
|
||||
|
||||
## Parity [v1.11.7](https://github.com/paritytech/parity-ethereum/releases/tag/v1.11.7) "Prosperity" (2018-07-17)
|
||||
## Parity-Ethereum [v1.11.7](https://github.com/paritytech/parity-ethereum/releases/tag/v1.11.7) "Prosperity" (2018-07-17)
|
||||
|
||||
Parity 1.11.7 "Prosperity" is a bug-fix release to improve performance and stability that marks the 1.11 release track as `stable`. Among other fixes, this release significantly addresses peering and synchronization issues. If you experienced such issues before, upgrading is highly recommended. If you rely on old versions of Parity, check out the `old-stable-1.10` branch, cherry-pick fixes, and compile your binaries independently. There will be no official support for any versions prior to 1.11.7, however (EOL).
|
||||
|
||||
|
||||
618
docs/CHANGELOG-2.0.md
Normal file
618
docs/CHANGELOG-2.0.md
Normal file
@@ -0,0 +1,618 @@
|
||||
## 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.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
- Stable release 2.0.8 backports ([#9748](https://github.com/paritytech/parity-ethereum/pull/9748))
|
||||
- Parity-version: mark 2.0.8 stable as critical
|
||||
- Use signed 256-bit integer for sstore gas refund substate ([#9746](https://github.com/paritytech/parity-ethereum/pull/9746))
|
||||
- Add --force to cargo audit install script ([#9735](https://github.com/paritytech/parity-ethereum/pull/9735))
|
||||
- Heads ref not present for branches beta and stable ([#9741](https://github.com/paritytech/parity-ethereum/pull/9741))
|
||||
- Aura: fix panic on extra_info with unsealed block ([#9755](https://github.com/paritytech/parity-ethereum/pull/9755))
|
||||
|
||||
|
||||
## Parity-Ethereum [v2.0.7](https://github.com/paritytech/parity-ethereum/releases/tag/v2.0.7) (2018-10-11)
|
||||
|
||||
Parity-Ethereum 2.0.7-stable is a release that introduces **Constantinople** to the Ethereum client. Upgrading is strongly recommended.
|
||||
|
||||
The following hardforks are supported by this release:
|
||||
|
||||
- Ropsten testnet block `4_230_000` on October 14, 2018 (Constantinople).
|
||||
- POA core mainnet block `5_329_160` on October 22, 2018 (CORE HF 2).
|
||||
- Kovan testnet block `9_200_000` on October 25, 2018 (Constantinople, KIP-{4,6}).
|
||||
|
||||
Running one of these networks, an upgrade to 2.0.7 or 2.1.2 is mandatory. More details can be found in Changelog below.
|
||||
|
||||
Please note, the following deprecations in our distribution of binaries:
|
||||
|
||||
- `arm*` targets are no longer served by parity, please consider (cross-)compiling from source yourself.
|
||||
- `i*86` targets are no longer served by parity, please consider upgrading your operating system.
|
||||
- Snapcraft is no longer maintained. please use binaries directly or your distro's repositories.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
- Stable Constantinople changes ([#9723](https://github.com/paritytech/parity-ethereum/pull/9723))
|
||||
- Ethash: implement EIP-1234 ([#9187](https://github.com/paritytech/parity-ethereum/pull/9187))
|
||||
- Implement EIP-1052 (EXTCODEHASH) and fix several issues in state account cache ([#9234](https://github.com/paritytech/parity-ethereum/pull/9234))
|
||||
- Comply EIP-86 with the new definition ([#9140](https://github.com/paritytech/parity-ethereum/pull/9140))
|
||||
- Implement KIP4: create2 for wasm ([#9277](https://github.com/paritytech/parity-ethereum/pull/9277))
|
||||
- `gasleft` extern implemented for WASM runtime (kip-6) ([#9357](https://github.com/paritytech/parity-ethereum/pull/9357))
|
||||
- Add EIP-1014 transition config flag ([#9268](https://github.com/paritytech/parity-ethereum/pull/9268))
|
||||
- Eip 1283: Net gas metering for SSTORE without dirty maps ([#9319](https://github.com/paritytech/parity-ethereum/pull/9319))
|
||||
- Update state tests execution model ([#9440](https://github.com/paritytech/parity-ethereum/pull/9440))
|
||||
- Fix checkpointing when creating contract failed ([#9514](https://github.com/paritytech/parity-ethereum/pull/9514))
|
||||
- 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))
|
||||
- Enable all Constantinople hard fork changes in constantinople_test.json ([#9505](https://github.com/paritytech/parity-ethereum/pull/9505))
|
||||
- Add constantinople conf to EvmTestClient. ([#9570](https://github.com/paritytech/parity-ethereum/pull/9570))
|
||||
- Hardfork the testnets ([#9562](https://github.com/paritytech/parity-ethereum/pull/9562))
|
||||
- Don't hash the init_code of CREATE. ([#9688](https://github.com/paritytech/parity-ethereum/pull/9688))
|
||||
- Implement CREATE2 gas changes and fix some potential overflowing ([#9694](https://github.com/paritytech/parity-ethereum/pull/9694))
|
||||
- Ethcore: delay ropsten hardfork ([#9704](https://github.com/paritytech/parity-ethereum/pull/9704))
|
||||
- Add hardcoded headers ([#9730](https://github.com/paritytech/parity-ethereum/pull/9730))
|
||||
- Gitlab ci: releasable_branches: change variables condition to schedule ([#9729](https://github.com/paritytech/parity-ethereum/pull/9729))
|
||||
- Hf in POA Core (2018-10-22) ([#9724](https://github.com/paritytech/parity-ethereum/pull/9724))
|
||||
- Backports for stable 2.0.7 ([#9648](https://github.com/paritytech/parity-ethereum/pull/9648))
|
||||
- Parity-version: bump stable to 2.0.7
|
||||
- Fix path to parity.h ([#9274](https://github.com/paritytech/parity-ethereum/pull/9274))
|
||||
- Ethcore: fix detection of major import ([#9552](https://github.com/paritytech/parity-ethereum/pull/9552))
|
||||
- Fix (light/provider) : Make `read_only executions` only read-only ([#9591](https://github.com/paritytech/parity-ethereum/pull/9591))
|
||||
- Hf in POA Sokol (2018-09-19) ([#9607](https://github.com/paritytech/parity-ethereum/pull/9607))
|
||||
- Fix failing node-table tests on mac os ([#9633](https://github.com/paritytech/parity-ethereum/pull/9633))
|
||||
- Fix(light_fetch): avoid race with BlockNumber::Latest ([#9665](https://github.com/paritytech/parity-ethereum/pull/9665))
|
||||
- Ci: Remove unnecessary pipes ([#9681](https://github.com/paritytech/parity-ethereum/pull/9681))
|
||||
- Docker: run parity as normal user ([#9689](https://github.com/paritytech/parity-ethereum/pull/9689))
|
||||
- Ci: Skip docs job for master and nightly ([#9693](https://github.com/paritytech/parity-ethereum/pull/9693))
|
||||
- Ethcore-io retries failed work steal ([#9651](https://github.com/paritytech/parity-ethereum/pull/9651))
|
||||
|
||||
## Parity-Ethereum [v2.0.6](https://github.com/paritytech/parity-ethereum/releases/tag/v2.0.6) (2018-09-20)
|
||||
|
||||
Parity-Ethereum 2.0.6-stable is a release that does not improve performance and stability; no changes were made.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
- Backports to 2.0.6 stable ([#9600](https://github.com/paritytech/parity-ethereum/pull/9600))
|
||||
- Ci: disable build cache for json-rpc-docs ([#9587](https://github.com/paritytech/parity-ethereum/pull/9587))
|
||||
|
||||
## Parity-Ethereum [v2.0.5](https://github.com/paritytech/parity-ethereum/releases/tag/v2.0.5) (2018-09-18)
|
||||
|
||||
Parity-Ethereum 2.0.5-stable is a bug-fix release to improve performance and stability.
|
||||
|
||||
Please, note:
|
||||
|
||||
- This release marks the 2.0 track of Parity-Ethereum as stable.
|
||||
- This release contains a low-severity issue with the web-sockets ports. [#9545](https://github.com/paritytech/parity-ethereum/pull/9545)
|
||||
- This release resolves a potential network fragmentation issue. [#9526](https://github.com/paritytech/parity-ethereum/pull/9526)
|
||||
- The default `gas_floor_target` was increased to `8_000_000`, the default `gas_cap` to `10_000_000`.
|
||||
- With this release, all versions of Parity Ethereum 1.x prior to 2.0 reached end of life.
|
||||
- Users are urged to upgrade to 2.0.5-stable or 2.1.0-beta.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
- Backports for 2.0.5 stable ([#9519](https://github.com/paritytech/parity-ethereum/pull/9519))
|
||||
- Parity-version: mark 2.0.5 track stable
|
||||
- Deps: bump fs-swap to 0.2.4
|
||||
- Remove initial token for WS. ([#9545](https://github.com/paritytech/parity-ethereum/pull/9545))
|
||||
- Version: mark release critical
|
||||
- Increase Gas-floor-target and Gas Cap ([#9564](https://github.com/paritytech/parity-ethereum/pull/9564))
|
||||
- Gas-floor-target increased to 8M by default
|
||||
- Gas-cap increased to 10M by default
|
||||
- Improve P2P discovery ([#9526](https://github.com/paritytech/parity-ethereum/pull/9526))
|
||||
- Add `target` to Rust traces
|
||||
- Network-devp2p: Don't remove discovery peer in main sync
|
||||
- Network-p2p: Refresh discovery more often
|
||||
- Update Peer discovery protocol
|
||||
- Run discovery more often when not enough nodes connected
|
||||
- Start the first discovery early
|
||||
- Update fast discovery rate
|
||||
- Fix tests
|
||||
- Fix `ping` tests
|
||||
- Fixing remote Node address ; adding PingPong round
|
||||
- Fix tests: update new +1 PingPong round
|
||||
- Increase slow Discovery rate
|
||||
- Check in flight FindNode before pings
|
||||
- Add `deprecated` to deprecated_echo_hash
|
||||
- Refactor `discovery_round` branching
|
||||
- Net_version caches network_id to avoid redundant acquire of sync read lock ([#9544](https://github.com/paritytech/parity-ethereum/pull/9544))
|
||||
- Net_version caches network_id to avoid redundant acquire of sync read lock, [#8746](https://github.com/paritytech/parity-ethereum/issues/8746)
|
||||
- Use lower_hex display formatting for `net_peerCount` RPC method
|
||||
- Update snapcraft.yaml ([#9530](https://github.com/paritytech/parity-ethereum/pull/9530))
|
||||
- Fix DEPRECATED `prepare`
|
||||
- Fix TODO https://bugs.launchpad.net/snapcraft/+bug/1778530
|
||||
|
||||
## Parity-Ethereum [v2.0.4](https://github.com/paritytech/parity-ethereum/releases/tag/v2.0.4) (2018-09-11)
|
||||
|
||||
Parity-Ethereum 2.0.4-beta is a bug-fix release to improve performance and stability:
|
||||
|
||||
- `eth_coinbase` now provides an actual account for light clients
|
||||
- don't report skipped primaries when empty steps are enabled in proof-of-authority networks
|
||||
- fix snapshot restoration failure on windows
|
||||
- check warp sync status for `eth_getWorks`
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
- Beta backports to 2.0.4 ([#9452](https://github.com/paritytech/parity-ethereum/pull/9452))
|
||||
- Parity-version: bump beta to 2.0.4
|
||||
- [Light/jsonrpc] Provide the actual account for `eth_coinbase` RPC and unify error handeling for light and full client ([#9383](https://github.com/paritytech/parity-ethereum/pull/9383))
|
||||
- Provide the actual `account` for eth_coinbase
|
||||
- The previous implementation always provided the `zero address` on `eth_coinbase` RPC. Now, instead the actual address is returned on success or an error when no account(s) is found!
|
||||
- Full client `eth_coinbase` return err
|
||||
- In the full-client return an error when no account is found instead of returning the `zero address`
|
||||
- Remove needless blocks on single import
|
||||
- Remove needless `static` lifetime on const
|
||||
- Fix `rpc_eth_author` test
|
||||
- Parity: print correct keys path on startup ([#9501](https://github.com/paritytech/parity-ethereum/pull/9501))
|
||||
- Aura: don't report skipped primaries when empty steps are enabled ([#9435](https://github.com/paritytech/parity-ethereum/pull/9435))
|
||||
- Only check warp syncing for eth_getWorks ([#9484](https://github.com/paritytech/parity-ethereum/pull/9484))
|
||||
- Only check warp syncing for eth_getWorks
|
||||
- Use SyncStatus::is_snapshot_syncing
|
||||
- Fix Snapshot restoration failure on Windows ([#9491](https://github.com/paritytech/parity-ethereum/pull/9491))
|
||||
- Close Blooms DB files before DB restoration
|
||||
- Address Grumbles
|
||||
|
||||
## Parity-Ethereum [v2.0.3](https://github.com/paritytech/parity-ethereum/releases/tag/v2.0.3) (2018-09-01)
|
||||
|
||||
Parity-Ethereum 2.0.3-beta is a bug-fix release to improve performance and stability. Hopefully. ;)
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
- Beta backports for 2.0.3 ([#9229](https://github.com/paritytech/parity-ethereum/pull/9229))
|
||||
- parity-version: bump beta to 2.0.2
|
||||
- remove ssl from dockerfiles, closes [#8880](https://github.com/paritytech/parity-ethereum/issues/8880) ([#9195](https://github.com/paritytech/parity-ethereum/pull/9195))
|
||||
- snap: remove ssl dependencies from snapcraft definition ([#9222](https://github.com/paritytech/parity-ethereum/pull/9222))
|
||||
- parity-version: bump beta to 2.0.3
|
||||
- Remove all dapp permissions related settings ([#9120](https://github.com/paritytech/parity-ethereum/pull/9120))
|
||||
- Completely remove all dapps struct from rpc
|
||||
- Remove unused pub use
|
||||
- Remove dapp policy/permission func in ethcore
|
||||
- Remove all dapps settings from rpc
|
||||
- Fix rpc tests
|
||||
- Use both origin and user_agent
|
||||
- Address grumbles
|
||||
- Address grumbles
|
||||
- Fix tests
|
||||
- Check if synced when using eth_getWork ([#9193](https://github.com/paritytech/parity-ethereum/issues/9193)) ([#9210](https://github.com/paritytech/parity-ethereum/pull/9210))
|
||||
- Check if synced when using eth_getWork ([#9193](https://github.com/paritytech/parity-ethereum/issues/9193))
|
||||
- Don't use fn syncing
|
||||
- Fix identation
|
||||
- Fix typo
|
||||
- Don't check for warping
|
||||
- rpc: avoid calling queue_info twice on eth_getWork
|
||||
- Fix potential as_usize overflow when casting from U256 in miner ([#9221](https://github.com/paritytech/parity-ethereum/pull/9221))
|
||||
- Allow old blocks from peers with lower difficulty ([#9226](https://github.com/paritytech/parity-ethereum/pull/9226))
|
||||
- Previously we only allow downloading of old blocks if the peer difficulty was greater than our syncing difficulty. This change allows downloading of blocks from peers where the difficulty is greater then the last downloaded old block.
|
||||
- Update Dockerfile ([#9242](https://github.com/paritytech/parity-ethereum/pull/9242))
|
||||
- Update Dockerfile
|
||||
- fix Docker build
|
||||
- fix dockerfile paths: parity -> parity-ethereum ([#9248](https://github.com/paritytech/parity-ethereum/pull/9248))
|
||||
- Propagate transactions for next 4 blocks. ([#9265](https://github.com/paritytech/parity-ethereum/pull/9265))
|
||||
- Closes [#9255](https://github.com/paritytech/parity-ethereum/issues/9255)
|
||||
- This PR also removes the limit of max 64 transactions per packet, currently we only attempt to prevent the packet size to go over 8MB. This will only be the case for super-large transactions or high-block-gas-limit chains.
|
||||
- Patching this is important only for chains that have blocks that can fit more than 4k transactions (over 86M block gas limit)
|
||||
- For mainnet, we should actually see a tiny bit faster propagation since instead of computing 4k pending set, we only need `4 * 8M / 21k = 1523` transactions.
|
||||
- Update tobalaba.json ([#9313](https://github.com/paritytech/parity-ethereum/pull/9313))
|
||||
- Fix load share ([#9321](https://github.com/paritytech/parity-ethereum/pull/9321))
|
||||
- fix(light_sync): calculate `load_share` properly
|
||||
- refactor(api.rs): extract `light_params` fn, add test
|
||||
- style(api.rs): add trailing commas
|
||||
- ethcore: fix pow difficulty validation ([#9328](https://github.com/paritytech/parity-ethereum/pull/9328))
|
||||
- ethcore: fix pow difficulty validation
|
||||
- ethcore: validate difficulty is not zero
|
||||
- ethcore: add issue link to regression test
|
||||
- ethcore: fix tests
|
||||
- ethcore: move difficulty_to_boundary to ethash crate
|
||||
- ethcore: reuse difficulty_to_boundary and boundary_to_difficulty
|
||||
- ethcore: fix grumbles in difficulty_to_boundary_aux
|
||||
- Light client `Provide default nonce in transactions when it´s missing` ([#9370](https://github.com/paritytech/parity-ethereum/pull/9370))
|
||||
- Provide `default_nonce` in tx's when it's missing
|
||||
- When `nonce` is missing in a `EthTransaction` will cause it to fall in these cases provide `default_nonce` value instead!
|
||||
- Changed http:// to https:// on Yasm link ([#9369](https://github.com/paritytech/parity-ethereum/pull/9369))
|
||||
- Changed http:// to https:// on Yasm link in README.md
|
||||
- Address grumbles
|
||||
- ethcore: kovan: delay activation of strict score validation ([#9406](https://github.com/paritytech/parity-ethereum/pull/9406))
|
||||
- Better support for eth_getLogs in light mode ([#9186](https://github.com/paritytech/parity-ethereum/pull/9186))
|
||||
- Light client on-demand request for headers range.
|
||||
- Cache headers in HeaderWithAncestors response.
|
||||
- Also fulfills request locally if all headers are in cache.
|
||||
- LightFetch::logs fetches missing headers on demand.
|
||||
- LightFetch::logs limit the number of headers requested at a time.
|
||||
- LightFetch::logs refactor header fetching logic.
|
||||
- Enforce limit on header range length in light client logs request.
|
||||
- Fix light request tests after struct change.
|
||||
- Respond to review comments.
|
||||
- Add update docs script to CI ([#9219](https://github.com/paritytech/parity-ethereum/pull/9219))
|
||||
- Add update docs script to CI
|
||||
- Added a script to CI that will use the jsonrpc tool to update rpc documentation then commit and push those to the wiki repo.
|
||||
- fix gitlab ci lint
|
||||
- Only apply jsonrpc docs update on tags
|
||||
- Update gitlab-rpc-docs.sh
|
||||
- Copy correct parity repo to jsonrpc folder
|
||||
- Copy correct parity repo to jsonrpc folder before attempting to build docs since the CI runner clones the repo as parity and not parity-ethereum.
|
||||
- Fix JSONRPC docs CI job
|
||||
- Update remote config in wiki repo before pushing changes using a github token for authentication. Add message to wiki tag when pushing changes. Use project directory to correctly copy parity code base into the jsonrpc repo for doc generation.
|
||||
- Fix set_remote_wiki function call in CI
|
||||
- Prevent blockchain & miner racing when accessing pending block. ([#9310](https://github.com/paritytech/parity-ethereum/pull/9310))
|
||||
- Prevent blockchain & miner racing when accessing pending block.
|
||||
- Fix unavailability of pending block during reseal.
|
||||
- Prevent sync restart if import queue full ([#9381](https://github.com/paritytech/parity-ethereum/pull/9381))
|
||||
- Add POA Networks: Core and Sokol ([#9413](https://github.com/paritytech/parity-ethereum/pull/9413))
|
||||
- ethcore: add poa network and sokol chainspecs
|
||||
- rpc: simplify chain spec docs
|
||||
- cli: rearrange networks by main/test and size/range
|
||||
- parity: don't blacklist 0x00a328 on sokol testnet
|
||||
- parity: add sokol and poanet to params and clean up a bit, add tests
|
||||
- ethcore: add the poa networks and clean up a bit
|
||||
- ethcore: fix path to poacore chain spec
|
||||
- parity: rename poa networks to poacore and poasokol
|
||||
- parity: fix configuration tests
|
||||
- parity: fix parameter tests
|
||||
- ethcore: rename POA Core and POA Sokol
|
||||
- Update tobalaba.json ([#9419](https://github.com/paritytech/parity-ethereum/pull/9419))
|
||||
- Update hardcoded sync ([#9421](https://github.com/paritytech/parity-ethereum/pull/9421))
|
||||
- Update foundation hardcoded header to block 6219777
|
||||
- Update ropsten hardcoded header to block 3917825
|
||||
- Update kovan hardcoded header to block 8511489
|
||||
|
||||
## Parity-Ethereum [v2.0.1](https://github.com/paritytech/parity-ethereum/releases/tag/v2.0.1) (2018-07-27)
|
||||
|
||||
Parity-Ethereum 2.0.1-beta is a bug-fix release to improve performance and stability.
|
||||
|
||||
Note, authorities in PoA networks based on the Aura engine, should upgrade their nodes to 1.11.8-stable or 2.0.1-beta as this release includes a critical fix.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
- Backports to 2.0.1-beta ([#9145](https://github.com/paritytech/parity-ethereum/pull/9145))
|
||||
- Parity-version: bump beta to 2.0.1
|
||||
- Ci: update version strings for snaps ([#9160](https://github.com/paritytech/parity-ethereum/pull/9160))
|
||||
- Be more graceful on Aura difficulty validation ([#9164](https://github.com/paritytech/parity-ethereum/pull/9164))
|
||||
- Be more graceful on Aura difficulty validation
|
||||
- Test: rejects_step_backwards
|
||||
- Test: proposer_switching
|
||||
- Test: rejects_future_block
|
||||
- Test: reports_skipped
|
||||
- Test: verify_empty_seal_steps
|
||||
- Remove node-health ([#9119](https://github.com/paritytech/parity-ethereum/pull/9119))
|
||||
- Remove node-health
|
||||
- Remove ntp_servers
|
||||
- Add --ntp-servers as legacy instead of removing it
|
||||
- Add --ntp-servers to deprecated args
|
||||
- Remove unused stuff
|
||||
- Remove _legacy_ntp_servers
|
||||
- Parity: fix UserDefaults json parser ([#9189](https://github.com/paritytech/parity-ethereum/pull/9189))
|
||||
- Parity: fix UserDefaults json parser
|
||||
- Parity: use serde_derive for UserDefaults
|
||||
- Parity: support deserialization of old UserDefault json format
|
||||
- Parity: make UserDefaults serde backwards compatible
|
||||
- Parity: tabify indentation in UserDefaults
|
||||
- Fix bugfix hard fork logic ([#9138](https://github.com/paritytech/parity-ethereum/pull/9138))
|
||||
- Fix bugfix hard fork logic
|
||||
- Remove dustProtectionTransition from bugfix category
|
||||
- Eip-168 is not enabled by default
|
||||
- Remove unnecessary 'static
|
||||
- Disable per-sender limit for local transactions. ([#9148](https://github.com/paritytech/parity-ethereum/pull/9148))
|
||||
- Disable per-sender limit for local transactions.
|
||||
- Add a missing new line.
|
||||
- Rpc: fix is_major_importing sync state condition ([#9112](https://github.com/paritytech/parity-ethereum/pull/9112))
|
||||
- Rpc: fix is_major_importing sync state condition
|
||||
- Rpc: fix informant printout when waiting for peers
|
||||
- Fix verification in ethcore-sync collect_blocks ([#9135](https://github.com/paritytech/parity-ethereum/pull/9135))
|
||||
- Docker: update hub dockerfile ([#9173](https://github.com/paritytech/parity-ethereum/pull/9173))
|
||||
- Update Dockerfile for hub
|
||||
- Update to Ubuntu Xenial 16.04
|
||||
- Fix cmake version
|
||||
- Docker: fix tab indentation in hub dockerfile
|
||||
- Rpc: fix broken merge
|
||||
- Rpc: remove node_health leftover from merge
|
||||
- Rpc: remove dapps leftover from merge
|
||||
|
||||
## Parity-Ethereum [v2.0.0](https://github.com/paritytech/parity-ethereum/releases/tag/v2.0.0) "Ethereum" (2018-07-18)
|
||||
|
||||
This is the Parity-Ethereum//v2.0.0-beta release, code-named "Ethereum", **YOLO!**
|
||||
|
||||
Please note, Parity-Ethereum//v2.0.0 comes with some breaking changes that might be interrupting your usual workflows. Please mind them before upgrading:
|
||||
|
||||
- The Parity client is now called _Parity-Ethereum_ to distinguish it from other software we provide, such as [_Parity-Bitcoin_](https://github.com/paritytech/parity-bitcoin/) and [_Parity-Polkadot_](https://github.com/paritytech/polkadot) ([#9052](https://github.com/paritytech/parity-ethereum/pull/9052)).
|
||||
- The public node and the user interface (a.k.a. _"Parity Wallet"_) are completely removed from the Parity-Ethereum//v2.0.0 client ([#8758](https://github.com/paritytech/parity-ethereum/pull/8758), [#8783](https://github.com/paritytech/parity-ethereum/pull/8783), [#8641](https://github.com/paritytech/parity-ethereum/pull/8641)). Users interested running a Parity Wallet, check out [the stand-alone UI application](https://github.com/Parity-JS/shell/releases).
|
||||
- The DApps subsystem was completely removed from the client ([#9017](https://github.com/paritytech/parity-ethereum/pull/9017), [#9107](https://github.com/paritytech/parity-ethereum/pull/9107)). Again, use the standalone wallet if you wish to continue working with them.
|
||||
- Windows and MacOS versions are not available as installer anymore and the system trays were removed ([#8778](https://github.com/paritytech/parity-ethereum/pull/8778)). If you desire to run Parity-Ethereum on Windows or MacOS, you still can get the binaries from our mirrors. Furthermore, MacOS users are encouraged [to use our homebrew tap](https://github.com/paritytech/homebrew-paritytech/).
|
||||
- Linux versions are not available as deb-/rpm-packages anymore ([#8887](https://github.com/paritytech/parity-ethereum/pull/8887)). Communities are encouraged to provide their own packages or maintain their own repositories, such as [Arch Linux does](https://www.archlinux.org/packages/community/x86_64/parity/) for instance.
|
||||
- MD5-checksums are completely replaced by SHA256-checksums ([#8884](https://github.com/paritytech/parity-ethereum/pull/8884)). This is also reflected on our homepage by now.
|
||||
- Deprecated, removed, or replaced CLI-options are hidden from client `--help` to further discourage their usage ([#8967](https://github.com/paritytech/parity-ethereum/pull/8967)).
|
||||
|
||||
Additional noteworthy changes to the client:
|
||||
|
||||
- Tracing of precompiled contracts when the transfer value is not zero ([#8486](https://github.com/paritytech/parity-ethereum/pull/8486))
|
||||
- _Parity-Ethereum_ as a library now provides APIs for running full and light nodes and a C interface ([#8412](https://github.com/paritytech/parity-ethereum/pull/8412)). Shared crates are now available in [_Parity-Common_](https://github.com/paritytech/parity-common) ([#9083](https://github.com/paritytech/parity-ethereum/pull/9083)).
|
||||
- The Morden database and keys are now moved to a `./Morden` subdirectory instead of `./test` which is by default used by Ropsten ([#8621](https://github.com/paritytech/parity-ethereum/pull/8621)).
|
||||
- Adding support for having an on-chain contract calculating the block rewards ([#8419](https://github.com/paritytech/parity-ethereum/pull/8419)).
|
||||
- Enforcing warp-only synchronization with `--warp-barrier [blocknumber]` flag ([#8228](https://github.com/paritytech/parity-ethereum/pull/8228)).
|
||||
- Adding a fork-choice and meta-data framework suitable for implementing Casper ([#8401](https://github.com/paritytech/parity-ethereum/pull/8401)).
|
||||
- Returning an error if RLP-size of a transaction exceeds a 300kB limit ([#8473](https://github.com/paritytech/parity-ethereum/pull/8473)).
|
||||
- Warp-sync is now resumable by keeping the downloaded chunks between client restarts. Also, it seeds downloaded snapshots for other nodes ([#8544](https://github.com/paritytech/parity-ethereum/pull/8544)).
|
||||
- The developer chain `--chain dev` now contains Byzantium features, this breaks existing developer chains ([#8717](https://github.com/paritytech/parity-ethereum/pull/8717)).
|
||||
- The EIP150, EIP160 and EIP161 forks are now to be specified in common params section of a chain-spec file instead of the Ethash params to enable these features on non-proof-of-work chains ([#8614](https://github.com/paritytech/parity-ethereum/pull/8614)). Please update your chain specs.
|
||||
- Allowing to disable local-by-default for transactions with new configurations ([#8882](https://github.com/paritytech/parity-ethereum/pull/8882)).
|
||||
- Never drop local transactions from different senders ([#9002](https://github.com/paritytech/parity-ethereum/pull/9002)).
|
||||
- Optimize pending transactions filter and fix ethstats reporting of pending transactions ([#9026](https://github.com/paritytech/parity-ethereum/pull/9026)).
|
||||
- Add separate database directory for light client allowing to run full and light nodes at the same time ([#9064](https://github.com/paritytech/parity-ethereum/pull/9064)).
|
||||
|
||||
If you are upgrading directly from versions 1.10.9 or earlier, please note important changes to our transaction-queue implementation, namely:
|
||||
|
||||
- The pool now limits transactions per-sender (see `--tx-queue-per-sender`), local transactions also have to obey that limit. Consider increasing the limit via CLI-flag when running benchmarks or sending a lot of transactions at once.
|
||||
- In case the pool is full, transactions received over the network, but originating from accounts that you have private keys for might not get accepted to the pool any more with higher priority. Consider running with larger pool size or submitting the transactions directly on the node via `eth_sendRawTransaction`.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
- Backports to 2.0.0-beta ([#9094](https://github.com/paritytech/parity-ethereum/pull/9094))
|
||||
- Parity-version: betalize 2.0
|
||||
- Multiple improvements to discovery ping handling ([#8771](https://github.com/paritytech/parity-ethereum/pull/8771))
|
||||
- Discovery: Only add nodes to routing table after receiving pong.
|
||||
- Discovery: Refactor packet creation into its own function.
|
||||
- Discovery: Additional testing for new add_node behavior.
|
||||
- Discovery: Track expiration of pings to non-yet-in-bucket nodes.
|
||||
- Discovery: Verify echo hash on pong packets.
|
||||
- Discovery: Track timeouts on FIND_NODE requests.
|
||||
- Discovery: Retry failed pings with exponential backoff.
|
||||
- !fixup Use slice instead of Vec for request_backoff.
|
||||
- Add separate database directory for light client ([#9064](https://github.com/paritytech/parity-ethereum/pull/9064))
|
||||
- Add separate default DB path for light client ([#8927](https://github.com/paritytech/parity-ethereum/pull/8927))
|
||||
- Improve readability
|
||||
- Revert "Replace `std::env::home_dir` with `dirs::home_dir` ([#9077](https://github.com/paritytech/parity-ethereum/pull/9077))" ([#9097](https://github.com/paritytech/parity-ethereum/pull/9097))
|
||||
- Revert "Replace `std::env::home_dir` with `dirs::home_dir` ([#9077](https://github.com/paritytech/parity-ethereum/pull/9077))"
|
||||
- This reverts commit 7e77932.
|
||||
- Restore some of the changes
|
||||
- Update parity-common
|
||||
- Offload cull to IoWorker. ([#9099](https://github.com/paritytech/parity-ethereum/pull/9099))
|
||||
- Fix work-notify. ([#9104](https://github.com/paritytech/parity-ethereum/pull/9104))
|
||||
- Update hidapi, fixes [#7542](https://github.com/paritytech/parity-ethereum/issues/7542) ([#9108](https://github.com/paritytech/parity-ethereum/pull/9108))
|
||||
- Docker: add cmake dependency ([#9111](https://github.com/paritytech/parity-ethereum/pull/9111))
|
||||
- Update light client hardcoded headers ([#9098](https://github.com/paritytech/parity-ethereum/pull/9098))
|
||||
- Insert Kovan hardcoded headers until 7690241
|
||||
- Insert Kovan hardcoded headers until block 7690241
|
||||
- Insert Ropsten hardcoded headers until 3612673
|
||||
- Insert Mainnet hardcoded headers until block 5941249
|
||||
- Make sure to produce full blocks. ([#9115](https://github.com/paritytech/parity-ethereum/pull/9115))
|
||||
- Insert ETC (classic) hardcoded headers until block 6170625 ([#9121](https://github.com/paritytech/parity-ethereum/pull/9121))
|
||||
- Fix verification in ethcore-sync collect_blocks ([#9135](https://github.com/paritytech/parity-ethereum/pull/9135))
|
||||
- Completely remove all dapps struct from rpc ([#9107](https://github.com/paritytech/parity-ethereum/pull/9107))
|
||||
- Completely remove all dapps struct from rpc
|
||||
- Remove unused pub use
|
||||
- `evm bench` fix broken dependencies ([#9134](https://github.com/paritytech/parity-ethereum/pull/9134))
|
||||
- `evm bench` use valid dependencies
|
||||
- Benchmarks of the `evm` used stale versions of a couple a crates that this commit fixes!
|
||||
- Fix warnings
|
||||
- Update snapcraft.yaml ([#9132](https://github.com/paritytech/parity-ethereum/pull/9132))
|
||||
- Parity Ethereum 2.0.0 ([#9052](https://github.com/paritytech/parity-ethereum/pull/9052))
|
||||
- Don't fetch snapshot chunks at random ([#9088](https://github.com/paritytech/parity-ethereum/pull/9088))
|
||||
- Remove the dapps system ([#9017](https://github.com/paritytech/parity-ethereum/pull/9017))
|
||||
- Fix nightly warnings ([#9080](https://github.com/paritytech/parity-ethereum/pull/9080))
|
||||
- Db: remove wal disabling / fast-and-loose option. ([#8963](https://github.com/paritytech/parity-ethereum/pull/8963))
|
||||
- Transactions hashes missing in trace_replayBlockTransactions method result [#8725](https://github.com/paritytech/parity-ethereum/issues/8725) ([#8883](https://github.com/paritytech/parity-ethereum/pull/8883))
|
||||
- Delete crates from parity-ethereum and fetch them from parity-common instead ([#9083](https://github.com/paritytech/parity-ethereum/pull/9083))
|
||||
- Updater verification ([#8787](https://github.com/paritytech/parity-ethereum/pull/8787))
|
||||
- Phrasing, precisions and typos in CLI help ([#9060](https://github.com/paritytech/parity-ethereum/pull/9060))
|
||||
- Some work towards iOS build ([#9045](https://github.com/paritytech/parity-ethereum/pull/9045))
|
||||
- Clean up deprecated options and add CHECK macro ([#9036](https://github.com/paritytech/parity-ethereum/pull/9036))
|
||||
- Replace `std::env::home_dir` with `dirs::home_dir` ([#9077](https://github.com/paritytech/parity-ethereum/pull/9077))
|
||||
- Fix warning in secret-store test ([#9074](https://github.com/paritytech/parity-ethereum/pull/9074))
|
||||
- Seedhashcompute remove needless `new` impl ([#9063](https://github.com/paritytech/parity-ethereum/pull/9063))
|
||||
- Remove trait bounds from several structs ([#9055](https://github.com/paritytech/parity-ethereum/pull/9055))
|
||||
- Docs: add changelog for 1.10.9 stable and 1.11.6 beta ([#9069](https://github.com/paritytech/parity-ethereum/pull/9069))
|
||||
- Enable test in `miner/pool/test` ([#9072](https://github.com/paritytech/parity-ethereum/pull/9072))
|
||||
- Fetch: replace futures-timer with tokio-timer ([#9066](https://github.com/paritytech/parity-ethereum/pull/9066))
|
||||
- Remove util-error ([#9054](https://github.com/paritytech/parity-ethereum/pull/9054))
|
||||
- Fixes for misbehavior reporting in AuthorityRound ([#8998](https://github.com/paritytech/parity-ethereum/pull/8998))
|
||||
- A last bunch of txqueue performance optimizations ([#9024](https://github.com/paritytech/parity-ethereum/pull/9024))
|
||||
- Reduce number of constraints for triedb types ([#9043](https://github.com/paritytech/parity-ethereum/pull/9043))
|
||||
- Bump fs-swap to 0.2.3 so it is compatible with osx 10.11 again ([#9050](https://github.com/paritytech/parity-ethereum/pull/9050))
|
||||
- Recursive test ([#9042](https://github.com/paritytech/parity-ethereum/pull/9042))
|
||||
- Introduce more optional features in ethcore ([#9020](https://github.com/paritytech/parity-ethereum/pull/9020))
|
||||
- Update ETSC bootnodes ([#9038](https://github.com/paritytech/parity-ethereum/pull/9038))
|
||||
- Optimize pending transactions filter ([#9026](https://github.com/paritytech/parity-ethereum/pull/9026))
|
||||
- Eip160/eip161 spec: u64 -> BlockNumber ([#9044](https://github.com/paritytech/parity-ethereum/pull/9044))
|
||||
- Move the C/C++ example to another directory ([#9032](https://github.com/paritytech/parity-ethereum/pull/9032))
|
||||
- Bump parking_lot to 0.6 ([#9013](https://github.com/paritytech/parity-ethereum/pull/9013))
|
||||
- Never drop local transactions from different senders. ([#9002](https://github.com/paritytech/parity-ethereum/pull/9002))
|
||||
- Precise HTTP or WebSockets for JSON-RPC options ([#9027](https://github.com/paritytech/parity-ethereum/pull/9027))
|
||||
- Recently rejected cache for transaction queue ([#9005](https://github.com/paritytech/parity-ethereum/pull/9005))
|
||||
- Make HashDB generic ([#8739](https://github.com/paritytech/parity-ethereum/pull/8739))
|
||||
- Only return error log for rustls ([#9025](https://github.com/paritytech/parity-ethereum/pull/9025))
|
||||
- Update Changelogs for 1.10.8 and 1.11.5 ([#9012](https://github.com/paritytech/parity-ethereum/pull/9012))
|
||||
- Attempt to graceful shutdown in case of panics ([#8999](https://github.com/paritytech/parity-ethereum/pull/8999))
|
||||
- Simplify kvdb error types ([#8924](https://github.com/paritytech/parity-ethereum/pull/8924))
|
||||
- Add option for user to set max size limit for RPC requests ([#9010](https://github.com/paritytech/parity-ethereum/pull/9010))
|
||||
- Bump ntp to 0.5.0 ([#9009](https://github.com/paritytech/parity-ethereum/pull/9009))
|
||||
- Removed duplicate dependency ([#9021](https://github.com/paritytech/parity-ethereum/pull/9021))
|
||||
- Minimal effective gas price in the queue ([#8934](https://github.com/paritytech/parity-ethereum/pull/8934))
|
||||
- Parity: fix db path when migrating to blooms db ([#8975](https://github.com/paritytech/parity-ethereum/pull/8975))
|
||||
- Preserve the current abort behavior ([#8995](https://github.com/paritytech/parity-ethereum/pull/8995))
|
||||
- Improve should_replace on NonceAndGasPrice ([#8980](https://github.com/paritytech/parity-ethereum/pull/8980))
|
||||
- Tentative fix for missing dependency error ([#8973](https://github.com/paritytech/parity-ethereum/pull/8973))
|
||||
- Refactor evm Instruction to be a c-like enum ([#8914](https://github.com/paritytech/parity-ethereum/pull/8914))
|
||||
- Fix deadlock in blockchain. ([#8977](https://github.com/paritytech/parity-ethereum/pull/8977))
|
||||
- Snap: downgrade rust to revision 1.26.2, ref snapcraft/+bug/1778530 ([#8984](https://github.com/paritytech/parity-ethereum/pull/8984))
|
||||
- Use local parity-dapps-glue instead of crate published at crates.io ([#8983](https://github.com/paritytech/parity-ethereum/pull/8983))
|
||||
- Parity: omit redundant last imported block number in light sync informant ([#8962](https://github.com/paritytech/parity-ethereum/pull/8962))
|
||||
- Disable hardware-wallets on platforms that don't support `libusb` ([#8464](https://github.com/paritytech/parity-ethereum/pull/8464))
|
||||
- Bump error-chain and quick_error versions ([#8972](https://github.com/paritytech/parity-ethereum/pull/8972))
|
||||
- Evm benchmark utilities ([#8944](https://github.com/paritytech/parity-ethereum/pull/8944))
|
||||
- Parity: hide legacy options from cli --help ([#8967](https://github.com/paritytech/parity-ethereum/pull/8967))
|
||||
- Scripts: fix docker build tag on latest using master ([#8952](https://github.com/paritytech/parity-ethereum/pull/8952))
|
||||
- Add type for passwords. ([#8920](https://github.com/paritytech/parity-ethereum/pull/8920))
|
||||
- Deps: bump fs-swap ([#8953](https://github.com/paritytech/parity-ethereum/pull/8953))
|
||||
- Eliminate some more `transmute()` ([#8879](https://github.com/paritytech/parity-ethereum/pull/8879))
|
||||
- Restrict vault.json permssion to owner and using random suffix for temp vault.json file ([#8932](https://github.com/paritytech/parity-ethereum/pull/8932))
|
||||
- Print SS.self_public when starting SS node ([#8949](https://github.com/paritytech/parity-ethereum/pull/8949))
|
||||
- Scripts: minor improvements ([#8930](https://github.com/paritytech/parity-ethereum/pull/8930))
|
||||
- Rpc: cap gas limit of local calls ([#8943](https://github.com/paritytech/parity-ethereum/pull/8943))
|
||||
- Docs: update changelogs ([#8931](https://github.com/paritytech/parity-ethereum/pull/8931))
|
||||
- Ethcore: fix compilation when using slow-blocks or evm-debug features ([#8936](https://github.com/paritytech/parity-ethereum/pull/8936))
|
||||
- Fixed blooms dir creation ([#8941](https://github.com/paritytech/parity-ethereum/pull/8941))
|
||||
- Update hardcoded headers ([#8925](https://github.com/paritytech/parity-ethereum/pull/8925))
|
||||
- New blooms database ([#8712](https://github.com/paritytech/parity-ethereum/pull/8712))
|
||||
- Ethstore: retry deduplication of wallet file names until success ([#8910](https://github.com/paritytech/parity-ethereum/pull/8910))
|
||||
- Update ropsten.json ([#8926](https://github.com/paritytech/parity-ethereum/pull/8926))
|
||||
- Include node identity in the P2P advertised client version. ([#8830](https://github.com/paritytech/parity-ethereum/pull/8830))
|
||||
- Allow disabling local-by-default for transactions with new config entry ([#8882](https://github.com/paritytech/parity-ethereum/pull/8882))
|
||||
- Allow Poll Lifetime to be configured via CLI ([#8885](https://github.com/paritytech/parity-ethereum/pull/8885))
|
||||
- Cleanup nibbleslice ([#8915](https://github.com/paritytech/parity-ethereum/pull/8915))
|
||||
- Hardware-wallets `Clean up things I missed in the latest PR` ([#8890](https://github.com/paritytech/parity-ethereum/pull/8890))
|
||||
- Remove debian/.deb and centos/.rpm packaging scripts ([#8887](https://github.com/paritytech/parity-ethereum/pull/8887))
|
||||
- Remove a weird emoji in new_social docs ([#8913](https://github.com/paritytech/parity-ethereum/pull/8913))
|
||||
- Minor fix in chain supplier and light provider ([#8906](https://github.com/paritytech/parity-ethereum/pull/8906))
|
||||
- Block 0 is valid in queries ([#8891](https://github.com/paritytech/parity-ethereum/pull/8891))
|
||||
- Fixed osx permissions ([#8901](https://github.com/paritytech/parity-ethereum/pull/8901))
|
||||
- Atomic create new files with permissions to owner in ethstore ([#8896](https://github.com/paritytech/parity-ethereum/pull/8896))
|
||||
- Add ETC Cooperative-run load balanced parity node ([#8892](https://github.com/paritytech/parity-ethereum/pull/8892))
|
||||
- Add support for --chain tobalaba ([#8870](https://github.com/paritytech/parity-ethereum/pull/8870))
|
||||
- Fix some warns on nightly ([#8889](https://github.com/paritytech/parity-ethereum/pull/8889))
|
||||
- Add new ovh bootnodes and fix port for foundation bootnode 3.2 ([#8886](https://github.com/paritytech/parity-ethereum/pull/8886))
|
||||
- Secretstore: service pack 1 ([#8435](https://github.com/paritytech/parity-ethereum/pull/8435))
|
||||
- Handle removed logs in filter changes and add geth compatibility field ([#8796](https://github.com/paritytech/parity-ethereum/pull/8796))
|
||||
- Fixed ipc leak, closes [#8774](https://github.com/paritytech/parity-ethereum/issues/8774) ([#8876](https://github.com/paritytech/parity-ethereum/pull/8876))
|
||||
- Scripts: remove md5 checksums ([#8884](https://github.com/paritytech/parity-ethereum/pull/8884))
|
||||
- Hardware_wallet/Ledger `Sign messages` + some refactoring ([#8868](https://github.com/paritytech/parity-ethereum/pull/8868))
|
||||
- Check whether we need resealing in miner and unwrap has_account in account_provider ([#8853](https://github.com/paritytech/parity-ethereum/pull/8853))
|
||||
- Docker: Fix alpine build ([#8878](https://github.com/paritytech/parity-ethereum/pull/8878))
|
||||
- Remove mac os installers etc ([#8875](https://github.com/paritytech/parity-ethereum/pull/8875))
|
||||
- Readme.md: update the list of dependencies ([#8864](https://github.com/paritytech/parity-ethereum/pull/8864))
|
||||
- Fix concurrent access to signer queue ([#8854](https://github.com/paritytech/parity-ethereum/pull/8854))
|
||||
- Tx permission contract improvement ([#8400](https://github.com/paritytech/parity-ethereum/pull/8400))
|
||||
- Limit the number of transactions in pending set ([#8777](https://github.com/paritytech/parity-ethereum/pull/8777))
|
||||
- Use sealing.enabled to emit eth_mining information ([#8844](https://github.com/paritytech/parity-ethereum/pull/8844))
|
||||
- Don't allocate in expect_valid_rlp unless necessary ([#8867](https://github.com/paritytech/parity-ethereum/pull/8867))
|
||||
- Fix Cli Return Code on --help for ethkey, ethstore & whisper ([#8863](https://github.com/paritytech/parity-ethereum/pull/8863))
|
||||
- Fix subcrate test compile ([#8862](https://github.com/paritytech/parity-ethereum/pull/8862))
|
||||
- Network-devp2p: downgrade logging to debug, add target ([#8784](https://github.com/paritytech/parity-ethereum/pull/8784))
|
||||
- Clearing up a comment about the prefix for signing ([#8828](https://github.com/paritytech/parity-ethereum/pull/8828))
|
||||
- Disable parallel verification and skip verifiying already imported txs. ([#8834](https://github.com/paritytech/parity-ethereum/pull/8834))
|
||||
- Devp2p: Move UDP socket handling from Discovery to Host. ([#8790](https://github.com/paritytech/parity-ethereum/pull/8790))
|
||||
- Fixed AuthorityRound deadlock on shutdown, closes [#8088](https://github.com/paritytech/parity-ethereum/issues/8088) ([#8803](https://github.com/paritytech/parity-ethereum/pull/8803))
|
||||
- Specify critical release flag per network ([#8821](https://github.com/paritytech/parity-ethereum/pull/8821))
|
||||
- Fix `deadlock_detection` feature branch compilation ([#8824](https://github.com/paritytech/parity-ethereum/pull/8824))
|
||||
- Use system allocator when profiling memory ([#8831](https://github.com/paritytech/parity-ethereum/pull/8831))
|
||||
- Added from and to to Receipt ([#8756](https://github.com/paritytech/parity-ethereum/pull/8756))
|
||||
- Ethcore: fix ancient block error msg handling ([#8832](https://github.com/paritytech/parity-ethereum/pull/8832))
|
||||
- Ci: Fix docker tags ([#8822](https://github.com/paritytech/parity-ethereum/pull/8822))
|
||||
- Parity: fix indentation in sync logging ([#8794](https://github.com/paritytech/parity-ethereum/pull/8794))
|
||||
- Removed obsolete IpcMode enum ([#8819](https://github.com/paritytech/parity-ethereum/pull/8819))
|
||||
- Remove UI related settings from CLI ([#8783](https://github.com/paritytech/parity-ethereum/pull/8783))
|
||||
- Remove windows tray and installer ([#8778](https://github.com/paritytech/parity-ethereum/pull/8778))
|
||||
- Docs: add changelogs for 1.10.6 and 1.11.3 ([#8810](https://github.com/paritytech/parity-ethereum/pull/8810))
|
||||
- Fix ancient blocks queue deadlock ([#8751](https://github.com/paritytech/parity-ethereum/pull/8751))
|
||||
- Disallow unsigned transactions in case EIP-86 is disabled ([#8802](https://github.com/paritytech/parity-ethereum/pull/8802))
|
||||
- Fix evmbin compilation ([#8795](https://github.com/paritytech/parity-ethereum/pull/8795))
|
||||
- Have space between feature cfg flag ([#8791](https://github.com/paritytech/parity-ethereum/pull/8791))
|
||||
- Rpc: fix address formatting in TransactionRequest Display ([#8786](https://github.com/paritytech/parity-ethereum/pull/8786))
|
||||
- Conditionally compile ethcore public test helpers ([#8743](https://github.com/paritytech/parity-ethereum/pull/8743))
|
||||
- Remove Result wrapper from AccountProvider in RPC impls ([#8763](https://github.com/paritytech/parity-ethereum/pull/8763))
|
||||
- Update `license header` and `scripts` ([#8666](https://github.com/paritytech/parity-ethereum/pull/8666))
|
||||
- Remove HostTrait altogether ([#8681](https://github.com/paritytech/parity-ethereum/pull/8681))
|
||||
- Ethcore-sync: fix connection to peers behind chain fork block ([#8710](https://github.com/paritytech/parity-ethereum/pull/8710))
|
||||
- Remove public node settings from cli ([#8758](https://github.com/paritytech/parity-ethereum/pull/8758))
|
||||
- Custom Error Messages on ENFILE and EMFILE IO Errors ([#8744](https://github.com/paritytech/parity-ethereum/pull/8744))
|
||||
- Ci: Fixes for Android Pipeline ([#8745](https://github.com/paritytech/parity-ethereum/pull/8745))
|
||||
- Remove NetworkService::config() ([#8653](https://github.com/paritytech/parity-ethereum/pull/8653))
|
||||
- Fix XOR distance calculation in discovery Kademlia impl ([#8589](https://github.com/paritytech/parity-ethereum/pull/8589))
|
||||
- Print warnings when fetching pending blocks ([#8711](https://github.com/paritytech/parity-ethereum/pull/8711))
|
||||
- Fix PoW blockchains sealing notifications in chain_new_blocks ([#8656](https://github.com/paritytech/parity-ethereum/pull/8656))
|
||||
- Remove -k/--insecure option from curl installer ([#8719](https://github.com/paritytech/parity-ethereum/pull/8719))
|
||||
- Ease tiny-keccak version requirements (1.4.1 -> 1.4) ([#8726](https://github.com/paritytech/parity-ethereum/pull/8726))
|
||||
- Bump tinykeccak to 1.4 ([#8728](https://github.com/paritytech/parity-ethereum/pull/8728))
|
||||
- Remove a couple of unnecessary `transmute()` ([#8736](https://github.com/paritytech/parity-ethereum/pull/8736))
|
||||
- Fix some nits using clippy ([#8731](https://github.com/paritytech/parity-ethereum/pull/8731))
|
||||
- Add 'interface' option to cli ([#8699](https://github.com/paritytech/parity-ethereum/pull/8699))
|
||||
- Remove unused function new_pow_test_spec ([#8735](https://github.com/paritytech/parity-ethereum/pull/8735))
|
||||
- Add a deadlock detection thread ([#8727](https://github.com/paritytech/parity-ethereum/pull/8727))
|
||||
- Fix local transactions policy. ([#8691](https://github.com/paritytech/parity-ethereum/pull/8691))
|
||||
- Shutdown the Snapshot Service early ([#8658](https://github.com/paritytech/parity-ethereum/pull/8658))
|
||||
- Network-devp2p: handle UselessPeer disconnect ([#8686](https://github.com/paritytech/parity-ethereum/pull/8686))
|
||||
- Fix compilation error on nightly rust ([#8707](https://github.com/paritytech/parity-ethereum/pull/8707))
|
||||
- Add a test for decoding corrupt data ([#8713](https://github.com/paritytech/parity-ethereum/pull/8713))
|
||||
- Update dev chain ([#8717](https://github.com/paritytech/parity-ethereum/pull/8717))
|
||||
- Remove unused imports ([#8722](https://github.com/paritytech/parity-ethereum/pull/8722))
|
||||
- Implement recursive Debug for Nodes in patrica_trie::TrieDB ([#8697](https://github.com/paritytech/parity-ethereum/pull/8697))
|
||||
- Parity: trim whitespace when parsing duration strings ([#8692](https://github.com/paritytech/parity-ethereum/pull/8692))
|
||||
- Set the request index to that of the current request ([#8683](https://github.com/paritytech/parity-ethereum/pull/8683))
|
||||
- Remove empty file ([#8705](https://github.com/paritytech/parity-ethereum/pull/8705))
|
||||
- Update mod.rs ([#8695](https://github.com/paritytech/parity-ethereum/pull/8695))
|
||||
- Use impl Future in the light client RPC helpers ([#8628](https://github.com/paritytech/parity-ethereum/pull/8628))
|
||||
- Fix cli signer ([#8682](https://github.com/paritytech/parity-ethereum/pull/8682))
|
||||
- Allow making direct RPC queries from the C API ([#8588](https://github.com/paritytech/parity-ethereum/pull/8588))
|
||||
- Remove the error when stopping the network ([#8671](https://github.com/paritytech/parity-ethereum/pull/8671))
|
||||
- Move connection_filter to the network crate ([#8674](https://github.com/paritytech/parity-ethereum/pull/8674))
|
||||
- Remove HostInfo::client_version() and secret() ([#8677](https://github.com/paritytech/parity-ethereum/pull/8677))
|
||||
- Refactor EIP150, EIP160 and EIP161 forks to be specified in CommonParams ([#8614](https://github.com/paritytech/parity-ethereum/pull/8614))
|
||||
- Parity: improve cli help and logging ([#8665](https://github.com/paritytech/parity-ethereum/pull/8665))
|
||||
- Updated tiny-keccak to 1.4.2 ([#8669](https://github.com/paritytech/parity-ethereum/pull/8669))
|
||||
- Remove the Keccak C library and use the pure Rust impl ([#8657](https://github.com/paritytech/parity-ethereum/pull/8657))
|
||||
- Remove HostInfo::next_nonce ([#8644](https://github.com/paritytech/parity-ethereum/pull/8644))
|
||||
- Fix not downloading old blocks ([#8642](https://github.com/paritytech/parity-ethereum/pull/8642))
|
||||
- Resumable warp-sync / Seed downloaded snapshots ([#8544](https://github.com/paritytech/parity-ethereum/pull/8544))
|
||||
- Don't open Browser post-install on Mac ([#8641](https://github.com/paritytech/parity-ethereum/pull/8641))
|
||||
- Changelog for 1.10.4-stable and 1.11.1-beta ([#8637](https://github.com/paritytech/parity-ethereum/pull/8637))
|
||||
- Typo ([#8640](https://github.com/paritytech/parity-ethereum/pull/8640))
|
||||
- Fork choice and metadata framework for Engine ([#8401](https://github.com/paritytech/parity-ethereum/pull/8401))
|
||||
- Check that the Android build doesn't dep on c++_shared ([#8538](https://github.com/paritytech/parity-ethereum/pull/8538))
|
||||
- Remove NetworkContext::io_channel() ([#8625](https://github.com/paritytech/parity-ethereum/pull/8625))
|
||||
- Fix light sync with initial validator-set contract ([#8528](https://github.com/paritytech/parity-ethereum/pull/8528))
|
||||
- Store morden db and keys in "path/to/parity/data/Morden" (ropsten uses "test", like before) ([#8621](https://github.com/paritytech/parity-ethereum/pull/8621))
|
||||
- ´main.rs´ typo ([#8629](https://github.com/paritytech/parity-ethereum/pull/8629))
|
||||
- Fix BlockReward contract "arithmetic operation overflow" ([#8611](https://github.com/paritytech/parity-ethereum/pull/8611))
|
||||
- Gitlab test script fixes ([#8573](https://github.com/paritytech/parity-ethereum/pull/8573))
|
||||
- Remove manually added text to the errors ([#8595](https://github.com/paritytech/parity-ethereum/pull/8595))
|
||||
- Fix account list double 0x display ([#8596](https://github.com/paritytech/parity-ethereum/pull/8596))
|
||||
- Typo: wrong indentation in kovan config ([#8610](https://github.com/paritytech/parity-ethereum/pull/8610))
|
||||
- Fix packet count when talking with PAR2 peers ([#8555](https://github.com/paritytech/parity-ethereum/pull/8555))
|
||||
- Use full qualified syntax for itertools::Itertools::flatten ([#8606](https://github.com/paritytech/parity-ethereum/pull/8606))
|
||||
- 2 tiny modification on snapshot ([#8601](https://github.com/paritytech/parity-ethereum/pull/8601))
|
||||
- Fix the mio test again ([#8602](https://github.com/paritytech/parity-ethereum/pull/8602))
|
||||
- Remove inject.js server-side injection for dapps ([#8539](https://github.com/paritytech/parity-ethereum/pull/8539))
|
||||
- Block_header can fail so return Result ([#8581](https://github.com/paritytech/parity-ethereum/pull/8581))
|
||||
- Block::decode() returns Result ([#8586](https://github.com/paritytech/parity-ethereum/pull/8586))
|
||||
- Fix compiler warning ([#8590](https://github.com/paritytech/parity-ethereum/pull/8590))
|
||||
- Fix Parity UI link ([#8600](https://github.com/paritytech/parity-ethereum/pull/8600))
|
||||
- Make mio optional in ethcore-io ([#8537](https://github.com/paritytech/parity-ethereum/pull/8537))
|
||||
- Attempt to fix intermittent test failures ([#8584](https://github.com/paritytech/parity-ethereum/pull/8584))
|
||||
- Changelog and Readme ([#8591](https://github.com/paritytech/parity-ethereum/pull/8591))
|
||||
- Added Dockerfile for alpine linux by @andresilva, closes [#3565](https://github.com/paritytech/parity-ethereum/issues/3565) ([#8587](https://github.com/paritytech/parity-ethereum/pull/8587))
|
||||
- Add whisper CLI to the pipelines ([#8578](https://github.com/paritytech/parity-ethereum/pull/8578))
|
||||
- Rename `whisper-cli binary` to `whisper` ([#8579](https://github.com/paritytech/parity-ethereum/pull/8579))
|
||||
- Changelog nit ([#8585](https://github.com/paritytech/parity-ethereum/pull/8585))
|
||||
- Remove unnecessary cloning in overwrite_with ([#8580](https://github.com/paritytech/parity-ethereum/pull/8580))
|
||||
- Handle socket address parsing errors ([#8545](https://github.com/paritytech/parity-ethereum/pull/8545))
|
||||
- Update CHANGELOG for 1.9, 1.10, and 1.11 ([#8556](https://github.com/paritytech/parity-ethereum/pull/8556))
|
||||
- Decoding headers can fail ([#8570](https://github.com/paritytech/parity-ethereum/pull/8570))
|
||||
- Refactoring `ethcore-sync` - Fixing warp-sync barrier ([#8543](https://github.com/paritytech/parity-ethereum/pull/8543))
|
||||
- Remove State::replace_backend ([#8569](https://github.com/paritytech/parity-ethereum/pull/8569))
|
||||
- Make trace-time publishable. ([#8568](https://github.com/paritytech/parity-ethereum/pull/8568))
|
||||
- Don't block sync when importing old blocks ([#8530](https://github.com/paritytech/parity-ethereum/pull/8530))
|
||||
- Trace precompiled contracts when the transfer value is not zero ([#8486](https://github.com/paritytech/parity-ethereum/pull/8486))
|
||||
- Parity as a library ([#8412](https://github.com/paritytech/parity-ethereum/pull/8412))
|
||||
- Rlp decode returns Result ([#8527](https://github.com/paritytech/parity-ethereum/pull/8527))
|
||||
- Node table sorting according to last contact data ([#8541](https://github.com/paritytech/parity-ethereum/pull/8541))
|
||||
- Keep all enacted blocks notify in order ([#8524](https://github.com/paritytech/parity-ethereum/pull/8524))
|
||||
- Ethcore, rpc, machine: refactor block reward application and tracing ([#8490](https://github.com/paritytech/parity-ethereum/pull/8490))
|
||||
- Consolidate crypto functionality in `ethcore-crypto`. ([#8432](https://github.com/paritytech/parity-ethereum/pull/8432))
|
||||
- Eip 145: Bitwise shifting instructions in EVM ([#8451](https://github.com/paritytech/parity-ethereum/pull/8451))
|
||||
- Remove expect ([#8536](https://github.com/paritytech/parity-ethereum/pull/8536))
|
||||
- Don't panic in import_block if invalid rlp ([#8522](https://github.com/paritytech/parity-ethereum/pull/8522))
|
||||
- Pass on storage keys tracing to handle the case when it is not modified ([#8491](https://github.com/paritytech/parity-ethereum/pull/8491))
|
||||
- Fetching logs by hash in blockchain database ([#8463](https://github.com/paritytech/parity-ethereum/pull/8463))
|
||||
- Transaction Pool improvements ([#8470](https://github.com/paritytech/parity-ethereum/pull/8470))
|
||||
- More changes for Android ([#8421](https://github.com/paritytech/parity-ethereum/pull/8421))
|
||||
- Enable WebAssembly and Byzantium for Ellaism ([#8520](https://github.com/paritytech/parity-ethereum/pull/8520))
|
||||
- Secretstore: merge two types of errors into single one + Error::is_non_fatal ([#8357](https://github.com/paritytech/parity-ethereum/pull/8357))
|
||||
- Hardware Wallet trait ([#8071](https://github.com/paritytech/parity-ethereum/pull/8071))
|
||||
- Directly return None if tracing is disabled ([#8504](https://github.com/paritytech/parity-ethereum/pull/8504))
|
||||
- Show imported messages for light client ([#8517](https://github.com/paritytech/parity-ethereum/pull/8517))
|
||||
- Remove unused dependency `bigint` ([#8505](https://github.com/paritytech/parity-ethereum/pull/8505))
|
||||
- `duration_ns: u64 -> duration: Duration` ([#8457](https://github.com/paritytech/parity-ethereum/pull/8457))
|
||||
- Return error if RLP size of transaction exceeds the limit ([#8473](https://github.com/paritytech/parity-ethereum/pull/8473))
|
||||
- Remove three old warp boot nodes. ([#8497](https://github.com/paritytech/parity-ethereum/pull/8497))
|
||||
- Update wasmi and pwasm-utils ([#8493](https://github.com/paritytech/parity-ethereum/pull/8493))
|
||||
- Update hardcodedSync for Ethereum, Kovan, and Ropsten ([#8489](https://github.com/paritytech/parity-ethereum/pull/8489))
|
||||
- Fix snap builds ([#8483](https://github.com/paritytech/parity-ethereum/pull/8483))
|
||||
- Bump master to 1.12 ([#8477](https://github.com/paritytech/parity-ethereum/pull/8477))
|
||||
- Don't require write lock when fetching status. ([#8481](https://github.com/paritytech/parity-ethereum/pull/8481))
|
||||
- Use rename_all for RichBlock and RichHeader serialization ([#8471](https://github.com/paritytech/parity-ethereum/pull/8471))
|
||||
@@ -12,15 +12,15 @@ blooms-db = { path = "../util/blooms-db" }
|
||||
bn = { git = "https://github.com/paritytech/bn", default-features = false }
|
||||
byteorder = "1.0"
|
||||
common-types = { path = "types" }
|
||||
crossbeam = "0.3"
|
||||
crossbeam = "0.4"
|
||||
ethash = { path = "../ethash" }
|
||||
ethcore-bloom-journal = { path = "../util/bloom" }
|
||||
parity-bytes = "0.1"
|
||||
hashdb = "0.2.1"
|
||||
memorydb = "0.2.1"
|
||||
patricia-trie = "0.2.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.1"
|
||||
parity-crypto = "0.2"
|
||||
error-chain = { version = "0.12", default-features = false }
|
||||
ethcore-io = { path = "../util/io" }
|
||||
ethcore-logger = { path = "../logger" }
|
||||
@@ -29,9 +29,9 @@ ethcore-stratum = { path = "./stratum", optional = true }
|
||||
ethcore-transaction = { path = "./transaction" }
|
||||
ethereum-types = "0.4"
|
||||
memory-cache = { path = "../util/memory_cache" }
|
||||
ethabi = "5.1.2"
|
||||
ethabi-derive = "5.1.3"
|
||||
ethabi-contract = "5.1.1"
|
||||
ethabi = "6.0"
|
||||
ethabi-derive = "6.0"
|
||||
ethabi-contract = "6.0"
|
||||
ethjson = { path = "../json" }
|
||||
ethkey = { path = "../ethkey" }
|
||||
ethstore = { path = "../ethstore" }
|
||||
@@ -47,7 +47,7 @@ parity-machine = { path = "../machine" }
|
||||
parking_lot = "0.6"
|
||||
rayon = "1.0"
|
||||
rand = "0.4"
|
||||
rlp = { version = "0.2.4", features = ["ethereum"] }
|
||||
rlp = { version = "0.3.0", features = ["ethereum"] }
|
||||
rlp_compress = { path = "../util/rlp_compress" }
|
||||
rlp_derive = { path = "../util/rlp_derive" }
|
||||
kvdb = "0.1"
|
||||
@@ -76,6 +76,7 @@ hardware-wallet = { path = "../hw" }
|
||||
fake-hardware-wallet = { path = "../util/fake-hardware-wallet" }
|
||||
|
||||
[dev-dependencies]
|
||||
env_logger = "0.4"
|
||||
tempdir = "0.3"
|
||||
trie-standardmap = "0.1"
|
||||
|
||||
@@ -102,6 +103,8 @@ evm-debug-tests = ["evm-debug", "evm/evm-debug-tests"]
|
||||
slow-blocks = []
|
||||
# Run JSON consensus tests.
|
||||
json-tests = ["ethcore-transaction/json-tests", "test-helpers", "tempdir"]
|
||||
# Skip JSON consensus tests with pending issues.
|
||||
ci-skip-issue = []
|
||||
# Run memory/cpu heavy tests.
|
||||
test-heavy = []
|
||||
# Compile benches
|
||||
|
||||
@@ -25,12 +25,10 @@ extern crate ethereum_types;
|
||||
extern crate parity_bytes as bytes;
|
||||
extern crate rustc_hex;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use bytes::BytesRef;
|
||||
use ethcore::builtin::Builtin;
|
||||
use ethcore::machine::EthereumMachine;
|
||||
use ethereum_types::{Address, U256};
|
||||
use ethereum_types::U256;
|
||||
use ethcore::ethereum::new_byzantium_test_machine;
|
||||
use rustc_hex::FromHex;
|
||||
use self::test::Bencher;
|
||||
|
||||
@@ -62,8 +62,8 @@ impl Finalize for Error {
|
||||
}
|
||||
|
||||
/// Cost calculation type. For low-gas usage we calculate costs using usize instead of U256
|
||||
pub trait CostType: Sized + From<usize> + Copy
|
||||
+ ops::Mul<Output=Self> + ops::Div<Output=Self> + ops::Add<Output=Self> +ops::Sub<Output=Self>
|
||||
pub trait CostType: Sized + From<usize> + Copy + Send
|
||||
+ ops::Mul<Output=Self> + ops::Div<Output=Self> + ops::Add<Output=Self> + ops::Sub<Output=Self>
|
||||
+ ops::Shr<usize, Output=Self> + ops::Shl<usize, Output=Self>
|
||||
+ cmp::Ord + fmt::Debug {
|
||||
/// Converts this cost into `U256`
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
//! Evm factory.
|
||||
//!
|
||||
use std::sync::Arc;
|
||||
use vm::{Vm, Schedule};
|
||||
use vm::{Exec, Schedule};
|
||||
use ethereum_types::U256;
|
||||
use super::vm::ActionParams;
|
||||
use super::interpreter::SharedCache;
|
||||
@@ -33,7 +33,7 @@ pub struct Factory {
|
||||
impl Factory {
|
||||
/// Create fresh instance of VM
|
||||
/// Might choose implementation depending on supplied gas.
|
||||
pub fn create(&self, params: ActionParams, schedule: &Schedule, depth: usize) -> Box<Vm> {
|
||||
pub fn create(&self, params: ActionParams, schedule: &Schedule, depth: usize) -> Box<Exec> {
|
||||
match self.evm {
|
||||
VMType::Interpreter => if Self::can_fit_in_usize(¶ms.gas) {
|
||||
Box::new(super::interpreter::Interpreter::<usize>::new(params, self.evm_cache.clone(), schedule, depth))
|
||||
|
||||
@@ -45,7 +45,7 @@ macro_rules! enum_with_from_u8 {
|
||||
enum_with_from_u8! {
|
||||
#[doc = "Virtual machine bytecode instruction."]
|
||||
#[repr(u8)]
|
||||
#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Debug)]
|
||||
#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Debug, Hash)]
|
||||
pub enum Instruction {
|
||||
#[doc = "halts execution"]
|
||||
STOP = 0x00,
|
||||
|
||||
@@ -176,9 +176,8 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
|
||||
Request::GasMem(default_gas, mem_needed(stack.peek(0), stack.peek(1))?)
|
||||
},
|
||||
instructions::SHA3 => {
|
||||
let w = overflowing!(add_gas_usize(Gas::from_u256(*stack.peek(1))?, 31));
|
||||
let words = w >> 5;
|
||||
let gas = Gas::from(schedule.sha3_gas) + (Gas::from(schedule.sha3_word_gas) * words);
|
||||
let words = overflowing!(to_word_size(Gas::from_u256(*stack.peek(1))?));
|
||||
let gas = overflowing!(Gas::from(schedule.sha3_gas).overflow_add(overflowing!(Gas::from(schedule.sha3_word_gas).overflow_mul(words))));
|
||||
Request::GasMem(gas, mem_needed(stack.peek(0), stack.peek(1))?)
|
||||
},
|
||||
instructions::CALLDATACOPY | instructions::CODECOPY | instructions::RETURNDATACOPY => {
|
||||
@@ -231,13 +230,24 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
|
||||
|
||||
Request::GasMemProvide(gas, mem, Some(requested))
|
||||
},
|
||||
instructions::CREATE | instructions::CREATE2 => {
|
||||
instructions::CREATE => {
|
||||
let start = stack.peek(1);
|
||||
let len = stack.peek(2);
|
||||
|
||||
let gas = Gas::from(schedule.create_gas);
|
||||
let mem = match instruction {
|
||||
instructions::CREATE => mem_needed(stack.peek(1), stack.peek(2))?,
|
||||
instructions::CREATE2 => mem_needed(stack.peek(2), stack.peek(3))?,
|
||||
_ => unreachable!("instruction can only be CREATE/CREATE2 checked above; qed"),
|
||||
};
|
||||
let mem = mem_needed(start, len)?;
|
||||
|
||||
Request::GasMemProvide(gas, mem, None)
|
||||
},
|
||||
instructions::CREATE2 => {
|
||||
let start = stack.peek(1);
|
||||
let len = stack.peek(2);
|
||||
|
||||
let base = Gas::from(schedule.create_gas);
|
||||
let word = overflowing!(to_word_size(Gas::from_u256(*len)?));
|
||||
let word_gas = overflowing!(Gas::from(schedule.sha3_word_gas).overflow_mul(word));
|
||||
let gas = overflowing!(base.overflow_add(word_gas));
|
||||
let mem = mem_needed(start, len)?;
|
||||
|
||||
Request::GasMemProvide(gas, mem, None)
|
||||
},
|
||||
@@ -287,8 +297,8 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
|
||||
},
|
||||
Request::GasMemCopy(gas, mem_size, copy) => {
|
||||
let (mem_gas_cost, new_mem_gas, new_mem_size) = self.mem_gas_cost(schedule, current_mem_size, &mem_size)?;
|
||||
let copy = overflowing!(add_gas_usize(copy, 31)) >> 5;
|
||||
let copy_gas = Gas::from(schedule.copy_gas) * copy;
|
||||
let copy = overflowing!(to_word_size(copy));
|
||||
let copy_gas = overflowing!(Gas::from(schedule.copy_gas).overflow_mul(copy));
|
||||
let gas = overflowing!(gas.overflow_add(copy_gas));
|
||||
let gas = overflowing!(gas.overflow_add(mem_gas_cost));
|
||||
|
||||
@@ -315,7 +325,7 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
|
||||
};
|
||||
|
||||
let current_mem_size = Gas::from(current_mem_size);
|
||||
let req_mem_size_rounded = (overflowing!(mem_size.overflow_add(Gas::from(31 as usize))) >> 5) << 5;
|
||||
let req_mem_size_rounded = overflowing!(to_word_size(*mem_size)) << 5;
|
||||
|
||||
let (mem_gas_cost, new_mem_gas) = if req_mem_size_rounded > current_mem_size {
|
||||
let new_mem_gas = gas_for_mem(req_mem_size_rounded)?;
|
||||
@@ -347,6 +357,16 @@ fn add_gas_usize<Gas: evm::CostType>(value: Gas, num: usize) -> (Gas, bool) {
|
||||
value.overflow_add(Gas::from(num))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn to_word_size<Gas: evm::CostType>(value: Gas) -> (Gas, bool) {
|
||||
let (gas, overflow) = add_gas_usize(value, 31);
|
||||
if overflow {
|
||||
return (gas, overflow);
|
||||
}
|
||||
|
||||
(gas >> 5, false)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn calculate_eip1283_sstore_gas<Gas: evm::CostType>(schedule: &Schedule, original: &U256, current: &U256, new: &U256) -> Gas {
|
||||
Gas::from(
|
||||
@@ -383,7 +403,7 @@ fn calculate_eip1283_sstore_gas<Gas: evm::CostType>(schedule: &Schedule, origina
|
||||
}
|
||||
|
||||
pub fn handle_eip1283_sstore_clears_refund(ext: &mut vm::Ext, original: &U256, current: &U256, new: &U256) {
|
||||
let sstore_clears_schedule = U256::from(ext.schedule().sstore_refund_gas);
|
||||
let sstore_clears_schedule = ext.schedule().sstore_refund_gas;
|
||||
|
||||
if current == new {
|
||||
// 1. If current value equals new value (this is a no-op), 200 gas is deducted.
|
||||
@@ -418,11 +438,11 @@ pub fn handle_eip1283_sstore_clears_refund(ext: &mut vm::Ext, original: &U256, c
|
||||
// 2.2.2. If original value equals new value (this storage slot is reset)
|
||||
if original.is_zero() {
|
||||
// 2.2.2.1. If original value is 0, add 19800 gas to refund counter.
|
||||
let refund = U256::from(ext.schedule().sstore_set_gas - ext.schedule().sload_gas);
|
||||
let refund = ext.schedule().sstore_set_gas - ext.schedule().sload_gas;
|
||||
ext.add_sstore_refund(refund);
|
||||
} else {
|
||||
// 2.2.2.2. Otherwise, add 4800 gas to refund counter.
|
||||
let refund = U256::from(ext.schedule().sstore_reset_gas - ext.schedule().sload_gas);
|
||||
let refund = ext.schedule().sstore_reset_gas - ext.schedule().sload_gas;
|
||||
ext.add_sstore_refund(refund);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ mod inner {
|
||||
use ethereum_types::U256;
|
||||
|
||||
use interpreter::stack::Stack;
|
||||
use instructions::{Instruction, InstructionInfo, INSTRUCTIONS};
|
||||
use instructions::{Instruction, InstructionInfo};
|
||||
use CostType;
|
||||
|
||||
macro_rules! evm_debug {
|
||||
@@ -97,7 +97,7 @@ mod inner {
|
||||
&self.spacing,
|
||||
pc,
|
||||
Self::color(instruction, info.name),
|
||||
instruction,
|
||||
instruction as u8,
|
||||
current_gas,
|
||||
Self::as_micro(&time),
|
||||
));
|
||||
@@ -117,18 +117,16 @@ mod inner {
|
||||
|
||||
pub fn done(&mut self) {
|
||||
// Print out stats
|
||||
let infos = &*INSTRUCTIONS;
|
||||
|
||||
let mut stats: Vec<(_,_)> = self.stats.drain().collect();
|
||||
stats.sort_by(|ref a, ref b| b.1.avg().cmp(&a.1.avg()));
|
||||
|
||||
print(format!("\n{}-------OPCODE STATS:", self.spacing));
|
||||
for (instruction, stats) in stats.into_iter() {
|
||||
let info = infos[instruction as usize];
|
||||
let info = instruction.info();
|
||||
print(format!("{}-------{:>19}(0x{:<2x}) count: {:4}, avg: {:10}μs",
|
||||
self.spacing,
|
||||
Self::color(instruction, info.name),
|
||||
instruction,
|
||||
instruction as u8,
|
||||
stats.count,
|
||||
stats.avg(),
|
||||
));
|
||||
|
||||
@@ -32,7 +32,8 @@ use ethereum_types::{U256, U512, H256, Address};
|
||||
|
||||
use vm::{
|
||||
self, ActionParams, ParamsType, ActionValue, CallType, MessageCallResult,
|
||||
ContractCreateResult, CreateContractAddress, ReturnData, GasLeft, Schedule
|
||||
ContractCreateResult, CreateContractAddress, ReturnData, GasLeft, Schedule,
|
||||
TrapKind, TrapError
|
||||
};
|
||||
|
||||
use evm::CostType;
|
||||
@@ -103,6 +104,7 @@ enum InstructionResult<Gas> {
|
||||
apply: bool,
|
||||
},
|
||||
StopExecution,
|
||||
Trap(TrapKind),
|
||||
}
|
||||
|
||||
enum Never {}
|
||||
@@ -161,6 +163,7 @@ pub enum InterpreterResult {
|
||||
Done(vm::Result<GasLeft>),
|
||||
/// The VM can continue to run.
|
||||
Continue,
|
||||
Trap(TrapKind),
|
||||
}
|
||||
|
||||
impl From<vm::Error> for InterpreterResult {
|
||||
@@ -182,22 +185,89 @@ pub struct Interpreter<Cost: CostType> {
|
||||
valid_jump_destinations: Option<Arc<BitSet>>,
|
||||
gasometer: Option<Gasometer<Cost>>,
|
||||
stack: VecStack<U256>,
|
||||
resume_output_range: Option<(U256, U256)>,
|
||||
resume_result: Option<InstructionResult<Cost>>,
|
||||
last_stack_ret_len: usize,
|
||||
_type: PhantomData<Cost>,
|
||||
}
|
||||
|
||||
impl<Cost: CostType> vm::Vm for Interpreter<Cost> {
|
||||
fn exec(&mut self, ext: &mut vm::Ext) -> vm::Result<GasLeft> {
|
||||
impl<Cost: 'static + CostType> vm::Exec for Interpreter<Cost> {
|
||||
fn exec(mut self: Box<Self>, ext: &mut vm::Ext) -> vm::ExecTrapResult<GasLeft> {
|
||||
loop {
|
||||
let result = self.step(ext);
|
||||
match result {
|
||||
InterpreterResult::Continue => {},
|
||||
InterpreterResult::Done(value) => return value,
|
||||
InterpreterResult::Done(value) => return Ok(value),
|
||||
InterpreterResult::Trap(trap) => match trap {
|
||||
TrapKind::Call(params) => {
|
||||
return Err(TrapError::Call(params, self));
|
||||
},
|
||||
TrapKind::Create(params, address) => {
|
||||
return Err(TrapError::Create(params, address, self));
|
||||
},
|
||||
},
|
||||
InterpreterResult::Stopped => panic!("Attempted to execute an already stopped VM.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Cost: 'static + CostType> vm::ResumeCall for Interpreter<Cost> {
|
||||
fn resume_call(mut self: Box<Self>, result: MessageCallResult) -> Box<vm::Exec> {
|
||||
{
|
||||
let this = &mut *self;
|
||||
let (out_off, out_size) = this.resume_output_range.take().expect("Box<ResumeCall> is obtained from a call opcode; resume_output_range is always set after those opcodes are executed; qed");
|
||||
|
||||
match result {
|
||||
MessageCallResult::Success(gas_left, data) => {
|
||||
let output = this.mem.writeable_slice(out_off, out_size);
|
||||
let len = cmp::min(output.len(), data.len());
|
||||
(&mut output[..len]).copy_from_slice(&data[..len]);
|
||||
|
||||
this.return_data = data;
|
||||
this.stack.push(U256::one());
|
||||
this.resume_result = Some(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater than current one")));
|
||||
},
|
||||
MessageCallResult::Reverted(gas_left, data) => {
|
||||
let output = this.mem.writeable_slice(out_off, out_size);
|
||||
let len = cmp::min(output.len(), data.len());
|
||||
(&mut output[..len]).copy_from_slice(&data[..len]);
|
||||
|
||||
this.return_data = data;
|
||||
this.stack.push(U256::zero());
|
||||
this.resume_result = Some(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater than current one")));
|
||||
},
|
||||
MessageCallResult::Failed => {
|
||||
this.stack.push(U256::zero());
|
||||
this.resume_result = Some(InstructionResult::Ok);
|
||||
},
|
||||
}
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<Cost: 'static + CostType> vm::ResumeCreate for Interpreter<Cost> {
|
||||
fn resume_create(mut self: Box<Self>, result: ContractCreateResult) -> Box<vm::Exec> {
|
||||
match result {
|
||||
ContractCreateResult::Created(address, gas_left) => {
|
||||
self.stack.push(address_to_u256(address));
|
||||
self.resume_result = Some(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater.")));
|
||||
},
|
||||
ContractCreateResult::Reverted(gas_left, return_data) => {
|
||||
self.stack.push(U256::zero());
|
||||
self.return_data = return_data;
|
||||
self.resume_result = Some(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater.")));
|
||||
},
|
||||
ContractCreateResult::Failed => {
|
||||
self.stack.push(U256::zero());
|
||||
self.resume_result = Some(InstructionResult::Ok);
|
||||
},
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<Cost: CostType> Interpreter<Cost> {
|
||||
/// Create a new `Interpreter` instance with shared cache.
|
||||
pub fn new(mut params: ActionParams, cache: Arc<SharedCache>, schedule: &Schedule, depth: usize) -> Interpreter<Cost> {
|
||||
@@ -215,6 +285,9 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
do_trace: true,
|
||||
mem: Vec::new(),
|
||||
return_data: ReturnData::empty(),
|
||||
last_stack_ret_len: 0,
|
||||
resume_output_range: None,
|
||||
resume_result: None,
|
||||
_type: PhantomData,
|
||||
}
|
||||
}
|
||||
@@ -244,51 +317,58 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
/// Inner helper function for step.
|
||||
#[inline(always)]
|
||||
fn step_inner(&mut self, ext: &mut vm::Ext) -> Result<Never, InterpreterResult> {
|
||||
let opcode = self.reader.code[self.reader.position];
|
||||
let instruction = Instruction::from_u8(opcode);
|
||||
self.reader.position += 1;
|
||||
let result = match self.resume_result.take() {
|
||||
Some(result) => result,
|
||||
None => {
|
||||
let opcode = self.reader.code[self.reader.position];
|
||||
let instruction = Instruction::from_u8(opcode);
|
||||
self.reader.position += 1;
|
||||
|
||||
// TODO: make compile-time removable if too much of a performance hit.
|
||||
self.do_trace = self.do_trace && ext.trace_next_instruction(
|
||||
self.reader.position - 1, opcode, self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas.as_u256(),
|
||||
);
|
||||
// TODO: make compile-time removable if too much of a performance hit.
|
||||
self.do_trace = self.do_trace && ext.trace_next_instruction(
|
||||
self.reader.position - 1, opcode, self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas.as_u256(),
|
||||
);
|
||||
|
||||
let instruction = match instruction {
|
||||
Some(i) => i,
|
||||
None => return Err(InterpreterResult::Done(Err(vm::Error::BadInstruction {
|
||||
instruction: opcode
|
||||
}))),
|
||||
let instruction = match instruction {
|
||||
Some(i) => i,
|
||||
None => return Err(InterpreterResult::Done(Err(vm::Error::BadInstruction {
|
||||
instruction: opcode
|
||||
}))),
|
||||
};
|
||||
|
||||
let info = instruction.info();
|
||||
self.last_stack_ret_len = info.ret;
|
||||
self.verify_instruction(ext, instruction, info)?;
|
||||
|
||||
// Calculate gas cost
|
||||
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));
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
evm_debug!({ self.informant.before_instruction(self.reader.position, instruction, info, &self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas, &self.stack) });
|
||||
|
||||
// Execute instruction
|
||||
let current_gas = self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas;
|
||||
let result = self.exec_instruction(
|
||||
current_gas, ext, instruction, requirements.provide_gas
|
||||
)?;
|
||||
|
||||
evm_debug!({ self.informant.after_instruction(instruction) });
|
||||
|
||||
result
|
||||
},
|
||||
};
|
||||
|
||||
let info = instruction.info();
|
||||
self.verify_instruction(ext, instruction, info)?;
|
||||
|
||||
// Calculate gas cost
|
||||
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());
|
||||
if let InstructionResult::Trap(trap) = result {
|
||||
return Err(InterpreterResult::Trap(trap));
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
evm_debug!({ informant.before_instruction(reader.position, instruction, info, &self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas, &stack) });
|
||||
|
||||
let (mem_written, store_written) = match self.do_trace {
|
||||
true => (Self::mem_written(instruction, &self.stack), Self::store_written(instruction, &self.stack)),
|
||||
false => (None, None),
|
||||
};
|
||||
|
||||
// Execute instruction
|
||||
let current_gas = self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas;
|
||||
let result = self.exec_instruction(
|
||||
current_gas, ext, instruction, requirements.provide_gas
|
||||
)?;
|
||||
|
||||
evm_debug!({ informant.after_instruction(instruction) });
|
||||
|
||||
if let InstructionResult::UnusedGas(ref gas) = result {
|
||||
self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas = self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas + *gas;
|
||||
}
|
||||
@@ -296,9 +376,8 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
if self.do_trace {
|
||||
ext.trace_executed(
|
||||
self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas.as_u256(),
|
||||
self.stack.peek_top(info.ret),
|
||||
mem_written.map(|(o, s)| (o, &(self.mem[o..o+s]))),
|
||||
store_written,
|
||||
self.stack.peek_top(self.last_stack_ret_len),
|
||||
&self.mem,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -306,8 +385,7 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
match result {
|
||||
InstructionResult::JumpToPosition(position) => {
|
||||
if self.valid_jump_destinations.is_none() {
|
||||
let code_hash = self.params.code_hash.clone().unwrap_or_else(|| keccak(self.reader.code.as_ref()));
|
||||
self.valid_jump_destinations = Some(self.cache.jump_destinations(&code_hash, &self.reader.code));
|
||||
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 = self.verify_jump(position, jump_destinations)?;
|
||||
@@ -451,21 +529,24 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
|
||||
let contract_code = self.mem.read_slice(init_off, init_size);
|
||||
|
||||
let create_result = ext.create(&create_gas.as_u256(), &endowment, contract_code, address_scheme);
|
||||
let create_result = ext.create(&create_gas.as_u256(), &endowment, contract_code, address_scheme, true);
|
||||
return match create_result {
|
||||
ContractCreateResult::Created(address, gas_left) => {
|
||||
Ok(ContractCreateResult::Created(address, gas_left)) => {
|
||||
self.stack.push(address_to_u256(address));
|
||||
Ok(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater.")))
|
||||
},
|
||||
ContractCreateResult::Reverted(gas_left, return_data) => {
|
||||
Ok(ContractCreateResult::Reverted(gas_left, return_data)) => {
|
||||
self.stack.push(U256::zero());
|
||||
self.return_data = return_data;
|
||||
Ok(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater.")))
|
||||
},
|
||||
ContractCreateResult::Failed => {
|
||||
Ok(ContractCreateResult::Failed) => {
|
||||
self.stack.push(U256::zero());
|
||||
Ok(InstructionResult::Ok)
|
||||
},
|
||||
Err(trap) => {
|
||||
Ok(InstructionResult::Trap(trap))
|
||||
},
|
||||
};
|
||||
},
|
||||
instructions::CALL | instructions::CALLCODE | instructions::DELEGATECALL | instructions::STATICCALL => {
|
||||
@@ -490,10 +571,10 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
let out_size = self.stack.pop_back();
|
||||
|
||||
// Add stipend (only CALL|CALLCODE when value > 0)
|
||||
let call_gas = call_gas + value.map_or_else(|| Cost::from(0), |val| match val.is_zero() {
|
||||
let call_gas = call_gas.overflow_add(value.map_or_else(|| Cost::from(0), |val| match val.is_zero() {
|
||||
false => Cost::from(ext.schedule().call_stipend),
|
||||
true => Cost::from(0),
|
||||
});
|
||||
})).0;
|
||||
|
||||
// Get sender & receive addresses, check if we have balance
|
||||
let (sender_address, receive_address, has_balance, call_type) = match instruction {
|
||||
@@ -524,13 +605,14 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
|
||||
let call_result = {
|
||||
let input = self.mem.read_slice(in_off, in_size);
|
||||
ext.call(&call_gas.as_u256(), sender_address, receive_address, value, input, &code_address, call_type)
|
||||
ext.call(&call_gas.as_u256(), sender_address, receive_address, value, input, &code_address, call_type, true)
|
||||
};
|
||||
|
||||
let output = self.mem.writeable_slice(out_off, out_size);
|
||||
self.resume_output_range = Some((out_off, out_size));
|
||||
|
||||
return match call_result {
|
||||
MessageCallResult::Success(gas_left, data) => {
|
||||
Ok(MessageCallResult::Success(gas_left, data)) => {
|
||||
let output = self.mem.writeable_slice(out_off, out_size);
|
||||
let len = cmp::min(output.len(), data.len());
|
||||
(&mut output[..len]).copy_from_slice(&data[..len]);
|
||||
|
||||
@@ -538,7 +620,8 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
self.return_data = data;
|
||||
Ok(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater than current one")))
|
||||
},
|
||||
MessageCallResult::Reverted(gas_left, data) => {
|
||||
Ok(MessageCallResult::Reverted(gas_left, data)) => {
|
||||
let output = self.mem.writeable_slice(out_off, out_size);
|
||||
let len = cmp::min(output.len(), data.len());
|
||||
(&mut output[..len]).copy_from_slice(&data[..len]);
|
||||
|
||||
@@ -546,10 +629,13 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
self.return_data = data;
|
||||
Ok(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater than current one")))
|
||||
},
|
||||
MessageCallResult::Failed => {
|
||||
Ok(MessageCallResult::Failed) => {
|
||||
self.stack.push(U256::zero());
|
||||
Ok(InstructionResult::Ok)
|
||||
},
|
||||
Err(trap) => {
|
||||
Ok(InstructionResult::Trap(trap))
|
||||
},
|
||||
};
|
||||
},
|
||||
instructions::RETURN => {
|
||||
@@ -634,7 +720,7 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
gasometer::handle_eip1283_sstore_clears_refund(ext, &original_val, ¤t_val, &val);
|
||||
} else {
|
||||
if !current_val.is_zero() && val.is_zero() {
|
||||
let sstore_clears_schedule = U256::from(ext.schedule().sstore_refund_gas);
|
||||
let sstore_clears_schedule = ext.schedule().sstore_refund_gas;
|
||||
ext.add_sstore_refund(sstore_clears_schedule);
|
||||
}
|
||||
}
|
||||
@@ -1095,10 +1181,10 @@ mod tests {
|
||||
use rustc_hex::FromHex;
|
||||
use vmtype::VMType;
|
||||
use factory::Factory;
|
||||
use vm::{self, Vm, ActionParams, ActionValue};
|
||||
use vm::{self, Exec, ActionParams, ActionValue};
|
||||
use vm::tests::{FakeExt, test_finalize};
|
||||
|
||||
fn interpreter(params: ActionParams, ext: &vm::Ext) -> Box<Vm> {
|
||||
fn interpreter(params: ActionParams, ext: &vm::Ext) -> Box<Exec> {
|
||||
Factory::new(VMType::Interpreter, 1).create(params, ext.schedule(), ext.depth())
|
||||
}
|
||||
|
||||
@@ -1118,7 +1204,7 @@ mod tests {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = interpreter(params, &ext);
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(ext.calls.len(), 1);
|
||||
@@ -1140,7 +1226,7 @@ mod tests {
|
||||
|
||||
let err = {
|
||||
let mut vm = interpreter(params, &ext);
|
||||
test_finalize(vm.exec(&mut ext)).err().unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).err().unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(err, ::vm::Error::OutOfBounds);
|
||||
|
||||
@@ -50,17 +50,22 @@ impl SharedCache {
|
||||
}
|
||||
|
||||
/// Get jump destinations bitmap for a contract.
|
||||
pub fn jump_destinations(&self, code_hash: &H256, code: &[u8]) -> Arc<BitSet> {
|
||||
if code_hash == &KECCAK_EMPTY {
|
||||
return Self::find_jump_destinations(code);
|
||||
}
|
||||
pub fn jump_destinations(&self, code_hash: &Option<H256>, code: &[u8]) -> Arc<BitSet> {
|
||||
if let Some(ref code_hash) = code_hash {
|
||||
if code_hash == &KECCAK_EMPTY {
|
||||
return Self::find_jump_destinations(code);
|
||||
}
|
||||
|
||||
if let Some(d) = self.jump_destinations.lock().get_mut(code_hash) {
|
||||
return d.0.clone();
|
||||
if let Some(d) = self.jump_destinations.lock().get_mut(code_hash) {
|
||||
return d.0.clone();
|
||||
}
|
||||
}
|
||||
|
||||
let d = Self::find_jump_destinations(code);
|
||||
self.jump_destinations.lock().insert(code_hash.clone(), Bits(d.clone()));
|
||||
|
||||
if let Some(ref code_hash) = code_hash {
|
||||
self.jump_destinations.lock().insert(*code_hash, Bits(d.clone()));
|
||||
}
|
||||
|
||||
d
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ fn test_add(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(79_988));
|
||||
@@ -59,7 +59,7 @@ fn test_sha3(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(79_961));
|
||||
@@ -79,7 +79,7 @@ fn test_address(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(79_995));
|
||||
@@ -101,7 +101,7 @@ fn test_origin(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(79_995));
|
||||
@@ -123,7 +123,7 @@ fn test_sender(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(79_995));
|
||||
@@ -158,7 +158,7 @@ fn test_extcodecopy(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(79_935));
|
||||
@@ -178,7 +178,7 @@ fn test_log_empty(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(99_619));
|
||||
@@ -210,7 +210,7 @@ fn test_log_sender(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(98_974));
|
||||
@@ -235,7 +235,7 @@ fn test_blockhash(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(79_974));
|
||||
@@ -257,7 +257,7 @@ fn test_calldataload(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(79_991));
|
||||
@@ -278,7 +278,7 @@ fn test_author(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(79_995));
|
||||
@@ -298,7 +298,7 @@ fn test_timestamp(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(79_995));
|
||||
@@ -318,7 +318,7 @@ fn test_number(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(79_995));
|
||||
@@ -338,7 +338,7 @@ fn test_difficulty(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(79_995));
|
||||
@@ -358,7 +358,7 @@ fn test_gas_limit(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(79_995));
|
||||
@@ -376,7 +376,7 @@ fn test_mul(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "000000000000000000000000000000000000000000000000734349397b853383");
|
||||
@@ -394,7 +394,7 @@ fn test_sub(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000012364ad0302");
|
||||
@@ -412,7 +412,7 @@ fn test_div(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "000000000000000000000000000000000000000000000000000000000002e0ac");
|
||||
@@ -430,7 +430,7 @@ fn test_div_zero(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000000");
|
||||
@@ -448,7 +448,7 @@ fn test_mod(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000076b4b");
|
||||
@@ -467,7 +467,7 @@ fn test_smod(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000076b4b");
|
||||
@@ -486,7 +486,7 @@ fn test_sdiv(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "000000000000000000000000000000000000000000000000000000000002e0ac");
|
||||
@@ -505,7 +505,7 @@ fn test_exp(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "90fd23767b60204c3d6fc8aec9e70a42a3f127140879c133a20129a597ed0c59");
|
||||
@@ -525,7 +525,7 @@ fn test_comparison(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000000");
|
||||
@@ -546,7 +546,7 @@ fn test_signed_comparison(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000000");
|
||||
@@ -567,7 +567,7 @@ fn test_bitops(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "00000000000000000000000000000000000000000000000000000000000000f0");
|
||||
@@ -590,7 +590,7 @@ fn test_addmod_mulmod(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000001");
|
||||
@@ -611,7 +611,7 @@ fn test_byte(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000000");
|
||||
@@ -630,7 +630,7 @@ fn test_signextend(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000fff");
|
||||
@@ -650,7 +650,7 @@ fn test_badinstruction_int() {
|
||||
|
||||
let err = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap_err()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap_err()
|
||||
};
|
||||
|
||||
match err {
|
||||
@@ -670,7 +670,7 @@ fn test_pop(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "00000000000000000000000000000000000000000000000000000000000000f0");
|
||||
@@ -690,7 +690,7 @@ fn test_extops(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000004"); // PC / CALLDATASIZE
|
||||
@@ -713,10 +713,10 @@ fn test_jumps(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(ext.sstore_clears, U256::from(ext.schedule().sstore_refund_gas));
|
||||
assert_eq!(ext.sstore_clears, ext.schedule().sstore_refund_gas as i128);
|
||||
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000000"); // 5!
|
||||
assert_store(&ext, 1, "0000000000000000000000000000000000000000000000000000000000000078"); // 5!
|
||||
assert_eq!(gas_left, U256::from(54_117));
|
||||
@@ -741,7 +741,7 @@ fn test_calls(factory: super::Factory) {
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_set_contains(&ext.calls, &FakeCall {
|
||||
@@ -782,7 +782,7 @@ fn test_create_in_staticcall(factory: super::Factory) {
|
||||
|
||||
let err = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap_err()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap_err()
|
||||
};
|
||||
|
||||
assert_eq!(err, vm::Error::MutableCallInStaticContext);
|
||||
@@ -1050,7 +1050,7 @@ fn push_two_pop_one_constantinople_test(factory: &super::Factory, opcode: u8, pu
|
||||
|
||||
let _ = {
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, result);
|
||||
|
||||
@@ -12,18 +12,18 @@ ethcore = { path = ".."}
|
||||
parity-bytes = "0.1"
|
||||
ethcore-transaction = { path = "../transaction" }
|
||||
ethereum-types = "0.4"
|
||||
memorydb = "0.2.1"
|
||||
patricia-trie = "0.2.1"
|
||||
memorydb = "0.3.0"
|
||||
patricia-trie = "0.3.0"
|
||||
patricia-trie-ethereum = { path = "../../util/patricia-trie-ethereum" }
|
||||
ethcore-network = { path = "../../util/network" }
|
||||
ethcore-io = { path = "../../util/io" }
|
||||
hashdb = "0.2.1"
|
||||
hashdb = "0.3.0"
|
||||
heapsize = "0.4"
|
||||
vm = { path = "../vm" }
|
||||
fastmap = { path = "../../util/fastmap" }
|
||||
rlp = { version = "0.2.4", features = ["ethereum"] }
|
||||
rlp = { version = "0.3.0", features = ["ethereum"] }
|
||||
rlp_derive = { path = "../../util/rlp_derive" }
|
||||
smallvec = "0.4"
|
||||
smallvec = "0.6"
|
||||
futures = "0.1"
|
||||
rand = "0.4"
|
||||
itertools = "0.5"
|
||||
|
||||
@@ -179,14 +179,15 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn corpus_inaccessible() {
|
||||
let mut cache = Cache::new(Default::default(), Duration::from_secs(5 * 3600));
|
||||
let duration = Duration::from_secs(20);
|
||||
let mut cache = Cache::new(Default::default(), duration.clone());
|
||||
|
||||
cache.set_gas_price_corpus(vec![].into());
|
||||
assert_eq!(cache.gas_price_corpus(), Some(vec![].into()));
|
||||
|
||||
{
|
||||
let corpus_time = &mut cache.corpus.as_mut().unwrap().1;
|
||||
*corpus_time = *corpus_time - Duration::from_secs(6 * 3600);
|
||||
*corpus_time = *corpus_time - duration;
|
||||
}
|
||||
assert!(cache.gas_price_corpus().is_none());
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ use ethcore::ids::BlockId;
|
||||
use ethereum_types::{H256, U256};
|
||||
use hashdb::HashDB;
|
||||
use keccak_hasher::KeccakHasher;
|
||||
use kvdb::DBValue;
|
||||
use memorydb::MemoryDB;
|
||||
use bytes::Bytes;
|
||||
use trie::{TrieMut, Trie, Recorder};
|
||||
@@ -52,13 +53,13 @@ pub const SIZE: u64 = 2048;
|
||||
/// A canonical hash trie. This is generic over any database it can query.
|
||||
/// See module docs for more details.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CHT<DB: HashDB<KeccakHasher>> {
|
||||
pub struct CHT<DB: HashDB<KeccakHasher, DBValue>> {
|
||||
db: DB,
|
||||
root: H256, // the root of this CHT.
|
||||
number: u64,
|
||||
}
|
||||
|
||||
impl<DB: HashDB<KeccakHasher>> CHT<DB> {
|
||||
impl<DB: HashDB<KeccakHasher, DBValue>> CHT<DB> {
|
||||
/// Query the root of the CHT.
|
||||
pub fn root(&self) -> H256 { self.root }
|
||||
|
||||
@@ -92,10 +93,10 @@ 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>>>
|
||||
pub fn build<F>(cht_num: u64, mut fetcher: F) -> Option<CHT<MemoryDB<KeccakHasher, DBValue>>>
|
||||
where F: FnMut(BlockId) -> Option<BlockInfo>
|
||||
{
|
||||
let mut db = MemoryDB::<KeccakHasher>::new();
|
||||
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;
|
||||
@@ -134,7 +135,7 @@ pub fn compute_root<I>(cht_num: u64, iterable: I) -> Option<H256>
|
||||
let start_num = start_number(cht_num) as usize;
|
||||
|
||||
for (i, (h, td)) in iterable.into_iter().take(SIZE as usize).enumerate() {
|
||||
v.push((key!(i + start_num).into_vec(), val!(h, td).into_vec()))
|
||||
v.push((key!(i + start_num), val!(h, td)))
|
||||
}
|
||||
|
||||
if v.len() == SIZE as usize {
|
||||
@@ -149,7 +150,7 @@ pub fn compute_root<I>(cht_num: u64, iterable: I) -> Option<H256>
|
||||
/// verify the given trie branch and extract the canonical hash and total difficulty.
|
||||
// TODO: better support for partially-checked queries.
|
||||
pub fn check_proof(proof: &[Bytes], num: u64, root: H256) -> Option<(H256, U256)> {
|
||||
let mut db = MemoryDB::<KeccakHasher>::new();
|
||||
let mut db = MemoryDB::<KeccakHasher, DBValue>::new();
|
||||
|
||||
for node in proof { db.insert(&node[..]); }
|
||||
let res = match TrieDB::new(&db, &root) {
|
||||
|
||||
@@ -33,7 +33,7 @@ use cht;
|
||||
use ethcore::block_status::BlockStatus;
|
||||
use ethcore::encoded;
|
||||
use ethcore::engines::epoch::{Transition as EpochTransition, PendingTransition as PendingEpochTransition};
|
||||
use ethcore::error::{Error, BlockImportError, BlockImportErrorKind, BlockError};
|
||||
use ethcore::error::{Error, EthcoreResult, ErrorKind as EthcoreErrorKind, BlockError};
|
||||
use ethcore::header::Header;
|
||||
use ethcore::ids::BlockId;
|
||||
use ethcore::spec::{Spec, SpecHardcodedSync};
|
||||
@@ -218,7 +218,7 @@ impl HeaderChain {
|
||||
) -> Result<Self, Error> {
|
||||
let mut live_epoch_proofs = ::std::collections::HashMap::default();
|
||||
|
||||
let genesis = ::rlp::encode(&spec.genesis_header()).into_vec();
|
||||
let genesis = ::rlp::encode(&spec.genesis_header());
|
||||
let decoded_header = spec.genesis_header();
|
||||
|
||||
let chain = if let Some(current) = db.get(col, CURRENT_KEY)? {
|
||||
@@ -351,7 +351,7 @@ impl HeaderChain {
|
||||
transaction: &mut DBTransaction,
|
||||
header: &Header,
|
||||
transition_proof: Option<Vec<u8>>,
|
||||
) -> Result<PendingChanges, BlockImportError> {
|
||||
) -> EthcoreResult<PendingChanges> {
|
||||
self.insert_inner(transaction, header, None, transition_proof)
|
||||
}
|
||||
|
||||
@@ -364,7 +364,7 @@ impl HeaderChain {
|
||||
header: &Header,
|
||||
total_difficulty: U256,
|
||||
transition_proof: Option<Vec<u8>>,
|
||||
) -> Result<PendingChanges, BlockImportError> {
|
||||
) -> EthcoreResult<PendingChanges> {
|
||||
self.insert_inner(transaction, header, Some(total_difficulty), transition_proof)
|
||||
}
|
||||
|
||||
@@ -374,7 +374,7 @@ impl HeaderChain {
|
||||
header: &Header,
|
||||
total_difficulty: Option<U256>,
|
||||
transition_proof: Option<Vec<u8>>,
|
||||
) -> Result<PendingChanges, BlockImportError> {
|
||||
) -> EthcoreResult<PendingChanges> {
|
||||
let hash = header.hash();
|
||||
let number = header.number();
|
||||
let parent_hash = *header.parent_hash();
|
||||
@@ -403,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(BlockImportErrorKind::Block)?
|
||||
.map_err(EthcoreErrorKind::Block)?
|
||||
};
|
||||
|
||||
parent_td + *header.difficulty()
|
||||
|
||||
@@ -22,7 +22,7 @@ use ethcore::block_status::BlockStatus;
|
||||
use ethcore::client::{ClientReport, EnvInfo, ClientIoMessage};
|
||||
use ethcore::engines::{epoch, EthEngine, EpochChange, EpochTransition, Proof};
|
||||
use ethcore::machine::EthereumMachine;
|
||||
use ethcore::error::{Error, BlockImportError};
|
||||
use ethcore::error::{Error, EthcoreResult};
|
||||
use ethcore::ids::BlockId;
|
||||
use ethcore::header::{BlockNumber, Header};
|
||||
use ethcore::verification::queue::{self, HeaderQueue};
|
||||
@@ -85,7 +85,7 @@ pub trait LightChainClient: Send + Sync {
|
||||
|
||||
/// Queue header to be verified. Required that all headers queued have their
|
||||
/// parent queued prior.
|
||||
fn queue_header(&self, header: Header) -> Result<H256, BlockImportError>;
|
||||
fn queue_header(&self, header: Header) -> EthcoreResult<H256>;
|
||||
|
||||
/// Attempt to get a block hash by block id.
|
||||
fn block_hash(&self, id: BlockId) -> Option<H256>;
|
||||
@@ -206,8 +206,8 @@ impl<T: ChainDataFetcher> Client<T> {
|
||||
}
|
||||
|
||||
/// Import a header to the queue for additional verification.
|
||||
pub fn import_header(&self, header: Header) -> Result<H256, BlockImportError> {
|
||||
self.queue.import(header).map_err(Into::into)
|
||||
pub fn import_header(&self, header: Header) -> EthcoreResult<H256> {
|
||||
self.queue.import(header).map_err(|(_, e)| e)
|
||||
}
|
||||
|
||||
/// Inquire about the status of a given header.
|
||||
@@ -313,7 +313,7 @@ impl<T: ChainDataFetcher> Client<T> {
|
||||
The node may not be able to synchronize further.", e);
|
||||
}
|
||||
|
||||
let epoch_proof = self.engine.is_epoch_end(
|
||||
let epoch_proof = self.engine.is_epoch_end_light(
|
||||
&verified_header,
|
||||
&|h| self.chain.block_header(BlockId::Hash(h)).and_then(|hdr| hdr.decode().ok()),
|
||||
&|h| self.chain.pending_transition(h),
|
||||
@@ -526,7 +526,7 @@ impl<T: ChainDataFetcher> LightChainClient for Client<T> {
|
||||
|
||||
fn chain_info(&self) -> BlockChainInfo { Client::chain_info(self) }
|
||||
|
||||
fn queue_header(&self, header: Header) -> Result<H256, BlockImportError> {
|
||||
fn queue_header(&self, header: Header) -> EthcoreResult<H256> {
|
||||
self.import_header(header)
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ use parking_lot::{Mutex, RwLock};
|
||||
use provider::Provider;
|
||||
use request::{Request, NetworkRequests as Requests, Response};
|
||||
use rlp::{RlpStream, Rlp};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::collections::{HashMap, HashSet, VecDeque};
|
||||
use std::fmt;
|
||||
use std::ops::{BitOr, BitAnd, Not};
|
||||
use std::sync::Arc;
|
||||
@@ -38,7 +38,7 @@ use std::time::{Duration, Instant};
|
||||
use self::request_credits::{Credits, FlowParams};
|
||||
use self::context::{Ctx, TickCtx};
|
||||
use self::error::Punishment;
|
||||
use self::load_timer::{LoadDistribution, NullStore};
|
||||
use self::load_timer::{LoadDistribution, NullStore, MOVING_SAMPLE_SIZE};
|
||||
use self::request_set::RequestSet;
|
||||
use self::id_guard::IdGuard;
|
||||
|
||||
@@ -70,6 +70,16 @@ const PROPAGATE_TIMEOUT_INTERVAL: Duration = Duration::from_secs(5);
|
||||
const RECALCULATE_COSTS_TIMEOUT: TimerToken = 3;
|
||||
const RECALCULATE_COSTS_INTERVAL: Duration = Duration::from_secs(60 * 60);
|
||||
|
||||
const STATISTICS_TIMEOUT: TimerToken = 4;
|
||||
const STATISTICS_INTERVAL: Duration = Duration::from_secs(15);
|
||||
|
||||
/// Maximum load share for the light server
|
||||
pub const MAX_LIGHTSERV_LOAD: f64 = 0.5;
|
||||
|
||||
/// Factor to multiply leecher count to cater for
|
||||
/// extra sudden connections (should be >= 1.0)
|
||||
pub const LEECHER_COUNT_FACTOR: f64 = 1.25;
|
||||
|
||||
// minimum interval between updates.
|
||||
const UPDATE_INTERVAL: Duration = Duration::from_millis(5000);
|
||||
|
||||
@@ -256,18 +266,18 @@ pub trait Handler: Send + Sync {
|
||||
pub struct Config {
|
||||
/// How many stored seconds of credits peers should be able to accumulate.
|
||||
pub max_stored_seconds: u64,
|
||||
/// How much of the total load capacity each peer should be allowed to take.
|
||||
pub load_share: f64,
|
||||
/// The network config median peers (used as default peer count)
|
||||
pub median_peers: f64,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
const LOAD_SHARE: f64 = 1.0 / 25.0;
|
||||
const MEDIAN_PEERS: f64 = 25.0;
|
||||
const MAX_ACCUMULATED: u64 = 60 * 5; // only charge for 5 minutes.
|
||||
|
||||
Config {
|
||||
max_stored_seconds: MAX_ACCUMULATED,
|
||||
load_share: LOAD_SHARE,
|
||||
median_peers: MEDIAN_PEERS,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -335,6 +345,42 @@ mod id_guard {
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides various statistics that could
|
||||
/// be used to compute costs
|
||||
pub struct Statistics {
|
||||
/// Samples of peer count
|
||||
peer_counts: VecDeque<usize>,
|
||||
}
|
||||
|
||||
impl Statistics {
|
||||
/// Create a new Statistics instance
|
||||
pub fn new() -> Self {
|
||||
Statistics {
|
||||
peer_counts: VecDeque::with_capacity(MOVING_SAMPLE_SIZE),
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a new peer_count sample
|
||||
pub fn add_peer_count(&mut self, peer_count: usize) {
|
||||
while self.peer_counts.len() >= MOVING_SAMPLE_SIZE {
|
||||
self.peer_counts.pop_front();
|
||||
}
|
||||
self.peer_counts.push_back(peer_count);
|
||||
}
|
||||
|
||||
/// Get the average peer count from previous samples. Is always >= 1.0
|
||||
pub fn avg_peer_count(&self) -> f64 {
|
||||
let len = self.peer_counts.len();
|
||||
if len == 0 {
|
||||
return 1.0;
|
||||
}
|
||||
let avg = self.peer_counts.iter()
|
||||
.fold(0, |sum: u32, &v| sum.saturating_add(v as u32)) as f64
|
||||
/ len as f64;
|
||||
avg.max(1.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// This is an implementation of the light ethereum network protocol, abstracted
|
||||
/// over a `Provider` of data and a p2p network.
|
||||
///
|
||||
@@ -359,6 +405,7 @@ pub struct LightProtocol {
|
||||
req_id: AtomicUsize,
|
||||
sample_store: Box<SampleStore>,
|
||||
load_distribution: LoadDistribution,
|
||||
statistics: RwLock<Statistics>,
|
||||
}
|
||||
|
||||
impl LightProtocol {
|
||||
@@ -369,9 +416,11 @@ impl LightProtocol {
|
||||
let genesis_hash = provider.chain_info().genesis_hash;
|
||||
let sample_store = params.sample_store.unwrap_or_else(|| Box::new(NullStore));
|
||||
let load_distribution = LoadDistribution::load(&*sample_store);
|
||||
// Default load share relative to median peers
|
||||
let load_share = MAX_LIGHTSERV_LOAD / params.config.median_peers;
|
||||
let flow_params = FlowParams::from_request_times(
|
||||
|kind| load_distribution.expected_time(kind),
|
||||
params.config.load_share,
|
||||
load_share,
|
||||
Duration::from_secs(params.config.max_stored_seconds),
|
||||
);
|
||||
|
||||
@@ -389,6 +438,7 @@ impl LightProtocol {
|
||||
req_id: AtomicUsize::new(0),
|
||||
sample_store,
|
||||
load_distribution,
|
||||
statistics: RwLock::new(Statistics::new()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -408,6 +458,16 @@ impl LightProtocol {
|
||||
)
|
||||
}
|
||||
|
||||
/// Get the number of active light peers downloading from the
|
||||
/// node
|
||||
pub fn leecher_count(&self) -> usize {
|
||||
let credit_limit = *self.flow_params.read().limit();
|
||||
// Count the number of peers that used some credit
|
||||
self.peers.read().iter()
|
||||
.filter(|(_, p)| p.lock().local_credits.current() < credit_limit)
|
||||
.count()
|
||||
}
|
||||
|
||||
/// Make a request to a peer.
|
||||
///
|
||||
/// Fails on: nonexistent peer, network error, peer not server,
|
||||
@@ -772,12 +832,16 @@ impl LightProtocol {
|
||||
fn begin_new_cost_period(&self, io: &IoContext) {
|
||||
self.load_distribution.end_period(&*self.sample_store);
|
||||
|
||||
let avg_peer_count = self.statistics.read().avg_peer_count();
|
||||
// Load share relative to average peer count +LEECHER_COUNT_FACTOR%
|
||||
let load_share = MAX_LIGHTSERV_LOAD / (avg_peer_count * LEECHER_COUNT_FACTOR);
|
||||
let new_params = Arc::new(FlowParams::from_request_times(
|
||||
|kind| self.load_distribution.expected_time(kind),
|
||||
self.config.load_share,
|
||||
load_share,
|
||||
Duration::from_secs(self.config.max_stored_seconds),
|
||||
));
|
||||
*self.flow_params.write() = new_params.clone();
|
||||
trace!(target: "pip", "New cost period: avg_peers={} ; cost_table:{:?}", avg_peer_count, new_params.cost_table());
|
||||
|
||||
let peers = self.peers.read();
|
||||
let now = Instant::now();
|
||||
@@ -797,6 +861,11 @@ impl LightProtocol {
|
||||
peer_info.awaiting_acknowledge = Some((now, new_params.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
fn tick_statistics(&self) {
|
||||
let leecher_count = self.leecher_count();
|
||||
self.statistics.write().add_peer_count(leecher_count);
|
||||
}
|
||||
}
|
||||
|
||||
impl LightProtocol {
|
||||
@@ -1099,6 +1168,8 @@ impl NetworkProtocolHandler for LightProtocol {
|
||||
.expect("Error registering sync timer.");
|
||||
io.register_timer(RECALCULATE_COSTS_TIMEOUT, RECALCULATE_COSTS_INTERVAL)
|
||||
.expect("Error registering request timer interval token.");
|
||||
io.register_timer(STATISTICS_TIMEOUT, STATISTICS_INTERVAL)
|
||||
.expect("Error registering statistics timer.");
|
||||
}
|
||||
|
||||
fn read(&self, io: &NetworkContext, peer: &PeerId, packet_id: u8, data: &[u8]) {
|
||||
@@ -1119,6 +1190,7 @@ impl NetworkProtocolHandler for LightProtocol {
|
||||
TICK_TIMEOUT => self.tick_handlers(&io),
|
||||
PROPAGATE_TIMEOUT => self.propagate_transactions(&io),
|
||||
RECALCULATE_COSTS_TIMEOUT => self.begin_new_cost_period(&io),
|
||||
STATISTICS_TIMEOUT => self.tick_statistics(),
|
||||
_ => warn!(target: "pip", "received timeout on unknown token {}", timer),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,9 +22,10 @@ use ethcore::client::{EachBlockWith, TestBlockChainClient};
|
||||
use ethcore::encoded;
|
||||
use ethcore::ids::BlockId;
|
||||
use ethereum_types::{H256, U256, Address};
|
||||
use net::{LightProtocol, Params, packet, Peer};
|
||||
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;
|
||||
@@ -150,7 +151,7 @@ impl Provider for TestProvider {
|
||||
|
||||
fn storage_proof(&self, req: request::CompleteStorageRequest) -> Option<request::StorageResponse> {
|
||||
Some(StorageResponse {
|
||||
proof: vec![::rlp::encode(&req.key_hash).into_vec()],
|
||||
proof: vec![::rlp::encode(&req.key_hash)],
|
||||
value: req.key_hash | req.address_hash,
|
||||
})
|
||||
}
|
||||
@@ -780,3 +781,34 @@ fn get_transaction_index() {
|
||||
let expected = Expect::Respond(packet::RESPONSE, response);
|
||||
proto.handle_packet(&expected, 1, packet::REQUEST, &request_body);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sync_statistics() {
|
||||
let mut stats = Statistics::new();
|
||||
|
||||
// Empty set should return 1.0
|
||||
assert_eq!(stats.avg_peer_count(), 1.0);
|
||||
|
||||
// Average < 1.0 should return 1.0
|
||||
stats.add_peer_count(0);
|
||||
assert_eq!(stats.avg_peer_count(), 1.0);
|
||||
|
||||
stats = Statistics::new();
|
||||
|
||||
const N: f64 = 50.0;
|
||||
|
||||
for i in 1..(N as usize + 1) {
|
||||
stats.add_peer_count(i);
|
||||
}
|
||||
|
||||
// Compute the average for the sum 1..N
|
||||
assert_eq!(stats.avg_peer_count(), N * (N + 1.0) / 2.0 / N);
|
||||
|
||||
for _ in 1..(MOVING_SAMPLE_SIZE + 1) {
|
||||
stats.add_peer_count(40);
|
||||
}
|
||||
|
||||
// Test that it returns the average of the last
|
||||
// `MOVING_SAMPLE_SIZE` values
|
||||
assert_eq!(stats.avg_peer_count(), 40.0);
|
||||
}
|
||||
|
||||
@@ -19,17 +19,18 @@
|
||||
//! 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 ethcore::executed::{Executed, ExecutionError};
|
||||
|
||||
use futures::{Poll, Future};
|
||||
use futures::sync::oneshot::{self, Receiver, Canceled};
|
||||
use futures::{Poll, Future, Async};
|
||||
use futures::sync::oneshot::{self, Receiver};
|
||||
use network::PeerId;
|
||||
use parking_lot::{RwLock, Mutex};
|
||||
use rand;
|
||||
use std::time::{Duration, SystemTime};
|
||||
|
||||
use net::{
|
||||
self, Handler, PeerStatus, Status, Capabilities,
|
||||
@@ -49,7 +50,45 @@ pub mod request;
|
||||
/// 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;
|
||||
|
||||
error_chain! {
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// relevant peer info.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
struct Peer {
|
||||
status: Status,
|
||||
capabilities: Capabilities,
|
||||
@@ -74,13 +113,21 @@ impl Peer {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Either an array of responses or a single error.
|
||||
type PendingResponse = self::error::Result<Vec<Response>>;
|
||||
|
||||
// Attempted request info and sender to put received value.
|
||||
struct Pending {
|
||||
requests: basic_request::Batch<CheckedRequest>,
|
||||
net_requests: basic_request::Batch<NetworkRequest>,
|
||||
required_capabilities: Capabilities,
|
||||
responses: Vec<Response>,
|
||||
sender: oneshot::Sender<Vec<Response>>,
|
||||
sender: oneshot::Sender<PendingResponse>,
|
||||
base_query_index: usize,
|
||||
remaining_query_count: usize,
|
||||
query_id_history: BTreeSet<PeerId>,
|
||||
inactive_time_limit: Option<SystemTime>,
|
||||
}
|
||||
|
||||
impl Pending {
|
||||
@@ -142,7 +189,9 @@ impl Pending {
|
||||
// if the requests are complete, send the result and consume self.
|
||||
fn try_complete(self) -> Option<Self> {
|
||||
if self.requests.is_complete() {
|
||||
let _ = self.sender.send(self.responses);
|
||||
if self.sender.send(Ok(self.responses)).is_err() {
|
||||
debug!(target: "on_demand", "Dropped oneshot channel receiver on complete request at query #{}", self.query_id_history.len());
|
||||
}
|
||||
None
|
||||
} else {
|
||||
Some(self)
|
||||
@@ -177,6 +226,25 @@ impl Pending {
|
||||
self.net_requests = builder.build();
|
||||
self.required_capabilities = capabilities;
|
||||
}
|
||||
|
||||
// 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 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// helper to guess capabilities required for a given batch of network requests.
|
||||
@@ -230,16 +298,21 @@ fn guess_capabilities(requests: &[CheckedRequest]) -> Capabilities {
|
||||
/// A future extracting the concrete output type of the generic adapter
|
||||
/// from a vector of responses.
|
||||
pub struct OnResponses<T: request::RequestAdapter> {
|
||||
receiver: Receiver<Vec<Response>>,
|
||||
receiver: Receiver<PendingResponse>,
|
||||
_marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: request::RequestAdapter> Future for OnResponses<T> {
|
||||
type Item = T::Out;
|
||||
type Error = Canceled;
|
||||
type Error = self::error::Error;
|
||||
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
self.receiver.poll().map(|async| async.map(T::extract_from))
|
||||
match self.receiver.poll() {
|
||||
Ok(Async::Ready(Ok(v))) => Ok(Async::Ready(T::extract_from(v))),
|
||||
Ok(Async::Ready(Err(e))) => Err(e),
|
||||
Ok(Async::NotReady) => Ok(Async::NotReady),
|
||||
Err(e) => Err(e.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,9 +326,12 @@ pub struct OnDemand {
|
||||
in_transit: RwLock<HashMap<ReqId, Pending>>,
|
||||
cache: Arc<Mutex<Cache>>,
|
||||
no_immediate_dispatch: bool,
|
||||
base_retry_count: usize,
|
||||
query_inactive_time_limit: Option<Duration>,
|
||||
}
|
||||
|
||||
impl OnDemand {
|
||||
|
||||
/// Create a new `OnDemand` service with the given cache.
|
||||
pub fn new(cache: Arc<Mutex<Cache>>) -> Self {
|
||||
OnDemand {
|
||||
@@ -264,6 +340,8 @@ impl OnDemand {
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,11 +360,11 @@ impl OnDemand {
|
||||
/// 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<Vec<Response>>, basic_request::NoSuchOutput>
|
||||
-> Result<Receiver<PendingResponse>, basic_request::NoSuchOutput>
|
||||
{
|
||||
let (sender, receiver) = oneshot::channel();
|
||||
if requests.is_empty() {
|
||||
assert!(sender.send(Vec::new()).is_ok(), "receiver still in scope; qed");
|
||||
assert!(sender.send(Ok(Vec::new())).is_ok(), "receiver still in scope; qed");
|
||||
return Ok(receiver);
|
||||
}
|
||||
|
||||
@@ -325,6 +403,10 @@ impl OnDemand {
|
||||
required_capabilities: capabilities,
|
||||
responses,
|
||||
sender,
|
||||
base_query_index: 0,
|
||||
remaining_query_count: 0,
|
||||
query_id_history: BTreeSet::new(),
|
||||
inactive_time_limit: None,
|
||||
});
|
||||
|
||||
Ok(receiver)
|
||||
@@ -363,30 +445,68 @@ impl OnDemand {
|
||||
let peers = self.peers.read();
|
||||
*pending = ::std::mem::replace(&mut *pending, Vec::new()).into_iter()
|
||||
.filter(|pending| !pending.sender.is_canceled())
|
||||
.filter_map(|pending| {
|
||||
.filter_map(|mut pending| {
|
||||
// the peer we dispatch to is chosen randomly
|
||||
let num_peers = peers.len();
|
||||
let rng = rand::random::<usize>() % cmp::max(num_peers, 1);
|
||||
for (peer_id, peer) in peers.iter().chain(peers.iter()).skip(rng).take(num_peers) {
|
||||
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 !peer.can_fulfill(&pending.required_capabilities) {
|
||||
continue
|
||||
if pending.remaining_query_count == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
match ctx.request_from(*peer_id, pending.net_requests.clone()) {
|
||||
Ok(req_id) => {
|
||||
trace!(target: "on_demand", "Dispatched request {} to peer {}", req_id, peer_id);
|
||||
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),
|
||||
}
|
||||
Err(net::Error::NoCredits) | Err(net::Error::NotServer) => {}
|
||||
Err(e) => debug!(target: "on_demand", "Error dispatching request to peer: {}", e),
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: maximum number of failures _when we have peers_.
|
||||
Some(pending)
|
||||
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.
|
||||
|
||||
@@ -406,6 +526,21 @@ impl OnDemand {
|
||||
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 {
|
||||
@@ -458,6 +593,16 @@ impl Handler for OnDemand {
|
||||
None => return,
|
||||
};
|
||||
|
||||
if responses.is_empty() {
|
||||
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
|
||||
// 1. ensure verification data filled.
|
||||
// 2. pending.requests.supply_response
|
||||
|
||||
@@ -1156,7 +1156,7 @@ mod tests {
|
||||
header.set_number(10_000);
|
||||
header.set_extra_data(b"test_header".to_vec());
|
||||
let hash = header.hash();
|
||||
let raw_header = encoded::Header::new(::rlp::encode(&header).into_vec());
|
||||
let raw_header = encoded::Header::new(::rlp::encode(&header));
|
||||
|
||||
let cache = Mutex::new(make_cache());
|
||||
assert!(HeaderByHash(hash.into()).check_response(&cache, &hash.into(), &[raw_header]).is_ok())
|
||||
@@ -1177,14 +1177,14 @@ mod tests {
|
||||
headers.reverse(); // because responses are in reverse order
|
||||
|
||||
let raw_headers = headers.iter()
|
||||
.map(|hdr| encoded::Header::new(::rlp::encode(hdr).into_vec()))
|
||||
.map(|hdr| encoded::Header::new(::rlp::encode(hdr)))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut invalid_successor = Header::new();
|
||||
invalid_successor.set_number(11);
|
||||
invalid_successor.set_parent_hash(headers[1].hash());
|
||||
|
||||
let raw_invalid_successor = encoded::Header::new(::rlp::encode(&invalid_successor).into_vec());
|
||||
let raw_invalid_successor = encoded::Header::new(::rlp::encode(&invalid_successor));
|
||||
|
||||
let cache = Mutex::new(make_cache());
|
||||
|
||||
@@ -1247,10 +1247,10 @@ mod tests {
|
||||
let mut body_stream = RlpStream::new_list(2);
|
||||
body_stream.begin_list(0).begin_list(0);
|
||||
|
||||
let req = Body(encoded::Header::new(::rlp::encode(&header).into_vec()).into());
|
||||
let req = Body(encoded::Header::new(::rlp::encode(&header)).into());
|
||||
|
||||
let cache = Mutex::new(make_cache());
|
||||
let response = encoded::Body::new(body_stream.drain().into_vec());
|
||||
let response = encoded::Body::new(body_stream.drain());
|
||||
assert!(req.check_response(&cache, &response).is_ok())
|
||||
}
|
||||
|
||||
@@ -1270,7 +1270,7 @@ mod tests {
|
||||
|
||||
header.set_receipts_root(receipts_root);
|
||||
|
||||
let req = BlockReceipts(encoded::Header::new(::rlp::encode(&header).into_vec()).into());
|
||||
let req = BlockReceipts(encoded::Header::new(::rlp::encode(&header)).into());
|
||||
|
||||
let cache = Mutex::new(make_cache());
|
||||
assert!(req.check_response(&cache, &receipts).is_ok())
|
||||
@@ -1318,7 +1318,7 @@ mod tests {
|
||||
header.set_state_root(root.clone());
|
||||
|
||||
let req = Account {
|
||||
header: encoded::Header::new(::rlp::encode(&header).into_vec()).into(),
|
||||
header: encoded::Header::new(::rlp::encode(&header)).into(),
|
||||
address: addr,
|
||||
};
|
||||
|
||||
@@ -1332,7 +1332,7 @@ mod tests {
|
||||
let code_hash = keccak(&code);
|
||||
let header = Header::new();
|
||||
let req = Code {
|
||||
header: encoded::Header::new(::rlp::encode(&header).into_vec()).into(),
|
||||
header: encoded::Header::new(::rlp::encode(&header)).into(),
|
||||
code_hash: code_hash.into(),
|
||||
};
|
||||
|
||||
|
||||
@@ -177,7 +177,7 @@ impl<T: ProvingBlockChainClient + ?Sized> Provider for T {
|
||||
|
||||
fn block_receipts(&self, req: request::CompleteReceiptsRequest) -> Option<request::ReceiptsResponse> {
|
||||
BlockChainClient::block_receipts(self, &req.hash)
|
||||
.map(|x| ::request::ReceiptsResponse { receipts: ::rlp::decode_list(&x) })
|
||||
.map(|x| ::request::ReceiptsResponse { receipts: x.receipts })
|
||||
}
|
||||
|
||||
fn account_proof(&self, req: request::CompleteAccountRequest) -> Option<request::AccountResponse> {
|
||||
|
||||
@@ -95,7 +95,7 @@ impl AccountTransactions {
|
||||
}
|
||||
|
||||
fn next_nonce(&self) -> U256 {
|
||||
self.current.last().map(|last| last.nonce + 1)
|
||||
self.current.last().map(|last| last.nonce.saturating_add(1.into()))
|
||||
.unwrap_or_else(|| *self.cur_nonce.value())
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ impl AccountTransactions {
|
||||
while let Some(tx) = self.future.remove(&next_nonce) {
|
||||
promoted.push(tx.hash);
|
||||
self.current.push(tx);
|
||||
next_nonce = next_nonce + 1;
|
||||
next_nonce = next_nonce.saturating_add(1.into());
|
||||
}
|
||||
|
||||
promoted
|
||||
|
||||
@@ -1676,7 +1676,7 @@ mod tests {
|
||||
let full_req = Request::Headers(req.clone());
|
||||
let res = HeadersResponse {
|
||||
headers: vec![
|
||||
::ethcore::encoded::Header::new(::rlp::encode(&Header::default()).into_vec())
|
||||
::ethcore::encoded::Header::new(::rlp::encode(&Header::default()))
|
||||
]
|
||||
};
|
||||
let full_res = Response::Headers(res.clone());
|
||||
|
||||
@@ -13,9 +13,9 @@ ethcore-network-devp2p = { path = "../../util/network-devp2p" }
|
||||
ethereum-types = "0.4"
|
||||
log = "0.4"
|
||||
parking_lot = "0.6"
|
||||
ethabi = "5.1.2"
|
||||
ethabi-derive = "5.1.3"
|
||||
ethabi-contract = "5.1.1"
|
||||
ethabi = "6.0"
|
||||
ethabi-derive = "6.0"
|
||||
ethabi-contract = "6.0"
|
||||
lru-cache = "0.1"
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
@@ -44,16 +44,16 @@ 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_contract!(peer_set, "PeerSet", "res/peer_set.json");
|
||||
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 {
|
||||
contract: peer_set::PeerSet,
|
||||
client: Weak<BlockChainClient>,
|
||||
contract_address: Address,
|
||||
permission_cache: Mutex<LruCache<(H256, NodeId), bool>>,
|
||||
@@ -63,7 +63,6 @@ impl NodeFilter {
|
||||
/// Create a new instance. Accepts a contract address.
|
||||
pub fn new(client: Weak<BlockChainClient>, contract_address: Address) -> NodeFilter {
|
||||
NodeFilter {
|
||||
contract: peer_set::PeerSet::default(),
|
||||
client,
|
||||
contract_address,
|
||||
permission_cache: Mutex::new(LruCache::new(MAX_CACHE_SIZE)),
|
||||
@@ -96,9 +95,9 @@ impl ConnectionFilter for NodeFilter {
|
||||
let id_low = H256::from_slice(&connecting_id[0..32]);
|
||||
let id_high = H256::from_slice(&connecting_id[32..64]);
|
||||
|
||||
let allowed = self.contract.functions()
|
||||
.connection_allowed()
|
||||
.call(own_low, own_high, id_low, id_high, &|data| client.call_contract(BlockId::Latest, address, data))
|
||||
let (data, decoder) = peer_set::functions::connection_allowed::call(own_low, own_high, id_low, id_high);
|
||||
let allowed = client.call_contract(BlockId::Latest, address, data)
|
||||
.and_then(|value| decoder.decode(&value).map_err(|e| e.to_string()))
|
||||
.unwrap_or_else(|e| {
|
||||
debug!("Error callling peer set contract: {:?}", e);
|
||||
false
|
||||
|
||||
@@ -7,12 +7,12 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
error-chain = { version = "0.12", default-features = false }
|
||||
ethabi = "5.1.2"
|
||||
ethabi-derive = "5.1.3"
|
||||
ethabi-contract = "5.1.1"
|
||||
ethabi = "6.0"
|
||||
ethabi-derive = "6.0"
|
||||
ethabi-contract = "6.0"
|
||||
ethcore = { path = ".." }
|
||||
parity-bytes = "0.1"
|
||||
parity-crypto = "0.1"
|
||||
parity-crypto = "0.2"
|
||||
ethcore-io = { path = "../../util/io" }
|
||||
ethcore-logger = { path = "../../logger" }
|
||||
ethcore-miner = { path = "../../miner" }
|
||||
@@ -26,10 +26,10 @@ heapsize = "0.4"
|
||||
keccak-hash = "0.1.2"
|
||||
log = "0.4"
|
||||
parking_lot = "0.6"
|
||||
patricia-trie = "0.2.1"
|
||||
patricia-trie = "0.3.0"
|
||||
patricia-trie-ethereum = { path = "../../util/patricia-trie-ethereum" }
|
||||
rand = "0.3"
|
||||
rlp = { version = "0.2.4", features = ["ethereum"] }
|
||||
rlp = { version = "0.3.0", features = ["ethereum"] }
|
||||
rlp_derive = { path = "../../util/rlp_derive" }
|
||||
rustc-hex = "1.0"
|
||||
serde = "1.0"
|
||||
|
||||
@@ -125,9 +125,9 @@ impl SecretStoreEncryptor {
|
||||
|
||||
// send HTTP request
|
||||
let method = if use_post {
|
||||
Method::Post
|
||||
Method::POST
|
||||
} else {
|
||||
Method::Get
|
||||
Method::GET
|
||||
};
|
||||
|
||||
let url = Url::from_str(&url).map_err(|e| ErrorKind::Encrypt(e.to_string()))?;
|
||||
|
||||
@@ -69,7 +69,6 @@ pub use error::{Error, ErrorKind};
|
||||
|
||||
use std::sync::{Arc, Weak};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::time::Duration;
|
||||
use ethereum_types::{H128, H256, U256, Address};
|
||||
use hash::keccak;
|
||||
use rlp::*;
|
||||
@@ -82,18 +81,19 @@ use ethcore::executed::{Executed};
|
||||
use transaction::{SignedTransaction, Transaction, Action, UnverifiedTransaction};
|
||||
use ethcore::{contract_address as ethcore_contract_address};
|
||||
use ethcore::client::{
|
||||
Client, ChainNotify, ChainRoute, ChainMessageType, ClientIoMessage, BlockId, CallContract
|
||||
Client, ChainNotify, NewBlocks, ChainMessageType, ClientIoMessage, BlockId, CallContract
|
||||
};
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
use ethcore::miner::{self, Miner, MinerService, pool_client::NonceCache};
|
||||
use ethcore::trace::{Tracer, VMTracer};
|
||||
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
|
||||
const DEFAULT_STUB_CONTRACT: &'static str = include_str!("../res/private.evm");
|
||||
|
||||
use_contract!(private, "PrivateContract", "res/private.json");
|
||||
use_contract!(private_contract, "res/private.json");
|
||||
|
||||
/// Initialization vector length.
|
||||
const INIT_VEC_LEN: usize = 16;
|
||||
@@ -101,6 +101,12 @@ const INIT_VEC_LEN: usize = 16;
|
||||
/// Size of nonce cache
|
||||
const NONCE_CACHE_SIZE: usize = 128;
|
||||
|
||||
/// Version for the initial private contract wrapper
|
||||
const INITIAL_PRIVATE_CONTRACT_VER: usize = 1;
|
||||
|
||||
/// Version for the private contract notification about private state changes added
|
||||
const PRIVATE_CONTRACT_WITH_NOTIFICATION_VER: usize = 2;
|
||||
|
||||
/// Configurtion for private transaction provider
|
||||
#[derive(Default, PartialEq, Debug, Clone)]
|
||||
pub struct ProviderConfig {
|
||||
@@ -202,29 +208,29 @@ impl Provider where {
|
||||
bail!(ErrorKind::BadTransactonType);
|
||||
}
|
||||
Action::Call(contract) => {
|
||||
let data = signed_transaction.rlp_bytes();
|
||||
let encrypted_transaction = self.encrypt(&contract, &Self::iv_from_transaction(&signed_transaction), &data)?;
|
||||
let private = PrivateTransaction::new(encrypted_transaction, contract);
|
||||
let data = signed_transaction.rlp_bytes();
|
||||
let encrypted_transaction = self.encrypt(&contract, &Self::iv_from_transaction(&signed_transaction), &data)?;
|
||||
let private = PrivateTransaction::new(encrypted_transaction, contract);
|
||||
// TODO [ToDr] Using BlockId::Latest is bad here,
|
||||
// the block may change in the middle of execution
|
||||
// causing really weird stuff to happen.
|
||||
// We should retrieve hash and stick to that. IMHO
|
||||
// best would be to change the API and only allow H256 instead of BlockID
|
||||
// in private-tx to avoid such mistakes.
|
||||
let contract_nonce = self.get_contract_nonce(&contract, BlockId::Latest)?;
|
||||
let private_state = self.execute_private_transaction(BlockId::Latest, &signed_transaction)?;
|
||||
trace!(target: "privatetx", "Private transaction created, encrypted transaction: {:?}, private state: {:?}", private, private_state);
|
||||
let contract_validators = self.get_validators(BlockId::Latest, &contract)?;
|
||||
trace!(target: "privatetx", "Required validators: {:?}", contract_validators);
|
||||
let private_state_hash = self.calculate_state_hash(&private_state, contract_nonce);
|
||||
trace!(target: "privatetx", "Hashed effective private state for sender: {:?}", private_state_hash);
|
||||
self.transactions_for_signing.write().add_transaction(private.hash(), signed_transaction, contract_validators, private_state, contract_nonce)?;
|
||||
self.broadcast_private_transaction(private.hash(), private.rlp_bytes().into_vec());
|
||||
Ok(Receipt {
|
||||
hash: tx_hash,
|
||||
contract_address: Some(contract),
|
||||
status_code: 0,
|
||||
})
|
||||
// the block may change in the middle of execution
|
||||
// causing really weird stuff to happen.
|
||||
// We should retrieve hash and stick to that. IMHO
|
||||
// best would be to change the API and only allow H256 instead of BlockID
|
||||
// in private-tx to avoid such mistakes.
|
||||
let contract_nonce = self.get_contract_nonce(&contract, BlockId::Latest)?;
|
||||
let private_state = self.execute_private_transaction(BlockId::Latest, &signed_transaction)?;
|
||||
trace!(target: "privatetx", "Private transaction created, encrypted transaction: {:?}, private state: {:?}", private, private_state);
|
||||
let contract_validators = self.get_validators(BlockId::Latest, &contract)?;
|
||||
trace!(target: "privatetx", "Required validators: {:?}", contract_validators);
|
||||
let private_state_hash = self.calculate_state_hash(&private_state, contract_nonce);
|
||||
trace!(target: "privatetx", "Hashed effective private state for sender: {:?}", private_state_hash);
|
||||
self.transactions_for_signing.write().add_transaction(private.hash(), signed_transaction, contract_validators, private_state, contract_nonce)?;
|
||||
self.broadcast_private_transaction(private.hash(), private.rlp_bytes());
|
||||
Ok(Receipt {
|
||||
hash: tx_hash,
|
||||
contract_address: Some(contract),
|
||||
status_code: 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -258,39 +264,39 @@ impl Provider where {
|
||||
match transaction.validator_account {
|
||||
None => {
|
||||
trace!(target: "privatetx", "Propagating transaction further");
|
||||
self.broadcast_private_transaction(private_hash, transaction.private_transaction.rlp_bytes().into_vec());
|
||||
self.broadcast_private_transaction(private_hash, transaction.private_transaction.rlp_bytes());
|
||||
return Ok(());
|
||||
}
|
||||
Some(validator_account) => {
|
||||
if !self.validator_accounts.contains(&validator_account) {
|
||||
trace!(target: "privatetx", "Propagating transaction further");
|
||||
self.broadcast_private_transaction(private_hash, transaction.private_transaction.rlp_bytes().into_vec());
|
||||
self.broadcast_private_transaction(private_hash, transaction.private_transaction.rlp_bytes());
|
||||
return Ok(());
|
||||
}
|
||||
let tx_action = transaction.transaction.action.clone();
|
||||
if let Action::Call(contract) = tx_action {
|
||||
// TODO [ToDr] Usage of BlockId::Latest
|
||||
let contract_nonce = self.get_contract_nonce(&contract, BlockId::Latest);
|
||||
if let Err(e) = contract_nonce {
|
||||
bail!("Cannot retrieve contract nonce: {:?}", e);
|
||||
}
|
||||
let contract_nonce = contract_nonce.expect("Error was checked before");
|
||||
let private_state = self.execute_private_transaction(BlockId::Latest, &transaction.transaction);
|
||||
if let Err(e) = private_state {
|
||||
bail!("Cannot retrieve private state: {:?}", e);
|
||||
}
|
||||
let private_state = private_state.expect("Error was checked before");
|
||||
let private_state_hash = self.calculate_state_hash(&private_state, contract_nonce);
|
||||
trace!(target: "privatetx", "Hashed effective private state for validator: {:?}", private_state_hash);
|
||||
let password = find_account_password(&self.passwords, &*self.accounts, &validator_account);
|
||||
let signed_state = self.accounts.sign(validator_account, password, private_state_hash);
|
||||
if let Err(e) = signed_state {
|
||||
bail!("Cannot sign the state: {:?}", e);
|
||||
}
|
||||
let signed_state = signed_state.expect("Error was checked before");
|
||||
let signed_private_transaction = SignedPrivateTransaction::new(private_hash, signed_state, None);
|
||||
trace!(target: "privatetx", "Sending signature for private transaction: {:?}", signed_private_transaction);
|
||||
self.broadcast_signed_private_transaction(signed_private_transaction.hash(), signed_private_transaction.rlp_bytes().into_vec());
|
||||
let contract_nonce = self.get_contract_nonce(&contract, BlockId::Latest);
|
||||
if let Err(e) = contract_nonce {
|
||||
bail!("Cannot retrieve contract nonce: {:?}", e);
|
||||
}
|
||||
let contract_nonce = contract_nonce.expect("Error was checked before");
|
||||
let private_state = self.execute_private_transaction(BlockId::Latest, &transaction.transaction);
|
||||
if let Err(e) = private_state {
|
||||
bail!("Cannot retrieve private state: {:?}", e);
|
||||
}
|
||||
let private_state = private_state.expect("Error was checked before");
|
||||
let private_state_hash = self.calculate_state_hash(&private_state, contract_nonce);
|
||||
trace!(target: "privatetx", "Hashed effective private state for validator: {:?}", private_state_hash);
|
||||
let password = find_account_password(&self.passwords, &*self.accounts, &validator_account);
|
||||
let signed_state = self.accounts.sign(validator_account, password, private_state_hash);
|
||||
if let Err(e) = signed_state {
|
||||
bail!("Cannot sign the state: {:?}", e);
|
||||
}
|
||||
let signed_state = signed_state.expect("Error was checked before");
|
||||
let signed_private_transaction = SignedPrivateTransaction::new(private_hash, signed_state, None);
|
||||
trace!(target: "privatetx", "Sending signature for private transaction: {:?}", signed_private_transaction);
|
||||
self.broadcast_signed_private_transaction(signed_private_transaction.hash(), signed_private_transaction.rlp_bytes());
|
||||
} else {
|
||||
bail!("Incorrect type of action for the transaction");
|
||||
}
|
||||
@@ -315,7 +321,7 @@ impl Provider where {
|
||||
let desc = match self.transactions_for_signing.read().get(&private_hash) {
|
||||
None => {
|
||||
// Not our transaction, broadcast further to peers
|
||||
self.broadcast_signed_private_transaction(signed_tx.hash(), signed_tx.rlp_bytes().into_vec());
|
||||
self.broadcast_signed_private_transaction(signed_tx.hash(), signed_tx.rlp_bytes());
|
||||
return Ok(());
|
||||
},
|
||||
Some(desc) => desc,
|
||||
@@ -326,7 +332,7 @@ impl Provider where {
|
||||
let mut signatures = desc.received_signatures.clone();
|
||||
signatures.push(signed_tx.signature());
|
||||
let rsv: Vec<Signature> = signatures.into_iter().map(|sign| sign.into_electrum().into()).collect();
|
||||
//Create public transaction
|
||||
// Create public transaction
|
||||
let public_tx = self.public_transaction(
|
||||
desc.state.clone(),
|
||||
&desc.original_transaction,
|
||||
@@ -335,7 +341,7 @@ impl Provider where {
|
||||
desc.original_transaction.gas_price
|
||||
)?;
|
||||
trace!(target: "privatetx", "Last required signature received, public transaction created: {:?}", public_tx);
|
||||
//Sign and add it to the queue
|
||||
// Sign and add it to the queue
|
||||
let chain_id = desc.original_transaction.chain_id();
|
||||
let hash = public_tx.hash(chain_id);
|
||||
let signer_account = self.signer_account.ok_or_else(|| ErrorKind::SignerAccountNotSet)?;
|
||||
@@ -349,13 +355,13 @@ impl Provider where {
|
||||
bail!(err);
|
||||
}
|
||||
}
|
||||
//Remove from store for signing
|
||||
// Remove from store for signing
|
||||
if let Err(err) = self.transactions_for_signing.write().remove(&private_hash) {
|
||||
warn!(target: "privatetx", "Failed to remove transaction from signing store, error: {:?}", err);
|
||||
bail!(err);
|
||||
}
|
||||
} else {
|
||||
//Add signature to the store
|
||||
// Add signature to the store
|
||||
match self.transactions_for_signing.write().add_signature(&private_hash, signed_tx.signature()) {
|
||||
Ok(_) => trace!(target: "privatetx", "Signature stored for private transaction"),
|
||||
Err(err) => {
|
||||
@@ -425,31 +431,23 @@ impl Provider where {
|
||||
}
|
||||
|
||||
fn get_decrypted_state(&self, address: &Address, block: BlockId) -> Result<Bytes, Error> {
|
||||
let contract = private::PrivateContract::default();
|
||||
let state = contract.functions()
|
||||
.state()
|
||||
.call(&|data| self.client.call_contract(block, *address, data))
|
||||
.map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?;
|
||||
|
||||
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| ErrorKind::Call(format!("Contract call failed {:?}", e)))?;
|
||||
self.decrypt(address, &state)
|
||||
}
|
||||
|
||||
fn get_decrypted_code(&self, address: &Address, block: BlockId) -> Result<Bytes, Error> {
|
||||
let contract = private::PrivateContract::default();
|
||||
let code = contract.functions()
|
||||
.code()
|
||||
.call(&|data| self.client.call_contract(block, *address, data))
|
||||
.map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?;
|
||||
|
||||
self.decrypt(address, &code)
|
||||
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| 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 contract = private::PrivateContract::default();
|
||||
Ok(contract.functions()
|
||||
.nonce()
|
||||
.call(&|data| self.client.call_contract(block, *address, data))
|
||||
.map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?)
|
||||
let (data, decoder) = private_contract::functions::nonce::call();
|
||||
let value = self.client.call_contract(block, *address, data)?;
|
||||
decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)).into())
|
||||
}
|
||||
|
||||
fn snapshot_to_storage(raw: Bytes) -> HashMap<H256, H256> {
|
||||
@@ -524,13 +522,11 @@ impl Provider where {
|
||||
|
||||
fn generate_constructor(validators: &[Address], code: Bytes, storage: Bytes) -> Bytes {
|
||||
let constructor_code = DEFAULT_STUB_CONTRACT.from_hex().expect("Default contract code is valid");
|
||||
let private = private::PrivateContract::default();
|
||||
private.constructor(constructor_code, validators.iter().map(|a| *a).collect::<Vec<Address>>(), code, storage)
|
||||
private_contract::constructor(constructor_code, validators.iter().map(|a| *a).collect::<Vec<Address>>(), code, storage)
|
||||
}
|
||||
|
||||
fn generate_set_state_call(signatures: &[Signature], storage: Bytes) -> Bytes {
|
||||
let private = private::PrivateContract::default();
|
||||
private.functions().set_state().input(
|
||||
private_contract::functions::set_state::encode_input(
|
||||
storage,
|
||||
signatures.iter().map(|s| {
|
||||
let mut v: [u8; 32] = [0; 32];
|
||||
@@ -604,11 +600,9 @@ impl Provider where {
|
||||
|
||||
/// Returns private validators for a contract.
|
||||
pub fn get_validators(&self, block: BlockId, address: &Address) -> Result<Vec<Address>, Error> {
|
||||
let contract = private::PrivateContract::default();
|
||||
Ok(contract.functions()
|
||||
.get_validators()
|
||||
.call(&|data| self.client.call_contract(block, *address, data))
|
||||
.map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?)
|
||||
let (data, decoder) = private_contract::functions::get_validators::call();
|
||||
let value = self.client.call_contract(block, *address, data)?;
|
||||
decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)).into())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -695,12 +689,11 @@ fn find_account_password(passwords: &Vec<Password>, account_provider: &AccountPr
|
||||
}
|
||||
|
||||
impl ChainNotify for Provider {
|
||||
fn new_blocks(&self, imported: Vec<H256>, _invalid: Vec<H256>, _route: ChainRoute, _sealed: Vec<H256>, _proposed: Vec<Bytes>, _duration: Duration) {
|
||||
if !imported.is_empty() {
|
||||
fn new_blocks(&self, new_blocks: NewBlocks) {
|
||||
if new_blocks.imported.is_empty() || new_blocks.has_more_blocks_to_import { return }
|
||||
trace!(target: "privatetx", "New blocks imported, try to prune the queue");
|
||||
if let Err(err) = self.process_verification_queue() {
|
||||
warn!(target: "privatetx", "Cannot prune private transactions queue. error: {:?}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
80
ethcore/res/ethereum/callisto.json
Normal file
80
ethcore/res/ethereum/callisto.json
Normal file
@@ -0,0 +1,80 @@
|
||||
{
|
||||
"name": "Callisto",
|
||||
"dataDir": "callisto",
|
||||
"engine": {
|
||||
"Ethash": {
|
||||
"params": {
|
||||
"minimumDifficulty": "0x020000",
|
||||
"difficultyBoundDivisor": "0x0800",
|
||||
"durationLimit": "0x0d",
|
||||
"blockReward": "0x16c4abbebea0100000",
|
||||
"homesteadTransition": 0,
|
||||
"blockRewardContractCode": "0x6080604052600436106100405763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663f91c28988114610045575b600080fd5b34801561005157600080fd5b50610071602460048035828101929082013591813591820191013561010a565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156100b557818101518382015260200161009d565b50505050905001838103825284818151815260200191508051906020019060200280838360005b838110156100f45781810151838201526020016100dc565b5050505090500194505050505060405180910390f35b606080808060008080803373fffffffffffffffffffffffffffffffffffffffe1461013457600080fd5b8a891461014057600080fd5b604080516003808252608082019092529060208201606080388339505060408051600380825260808201909252929850905060208201606080388339019050509450733c06f218ce6dd8e2c535a8925a2edf81674984d98660018151811015156101a657fe5b73ffffffffffffffffffffffffffffffffffffffff9092166020928302909101909101528451680340aad21b3b70000090869060019081106101e457fe5b6020908102909101015285517374682fc32007af0b6118f259cbe7bccc21641600908790600290811061021357fe5b73ffffffffffffffffffffffffffffffffffffffff909216602092830290910190910152845168068155a43676e00000908690600290811061025157fe5b60209081029091010152600093505b8a8410156103ce5789898581811061027457fe5b9050602002013561ffff1661ffff16600014156103235767b6255df5f50080006000198c01026816c4abbebea01000000192508b8b858181106102b357fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff168660008151811015156102df57fe5b73ffffffffffffffffffffffffffffffffffffffff909216602092830290910190910152845183908690600090811061031457fe5b602090810290910101526103c3565b60648a8a8681811061033157fe5b9050602002013561ffff1661ffff161015156103c35760648a8a8681811061035557fe5b9050602002013561ffff1603915060038260080361ffff166816c4abbebea0100000029060020a900490506103b4868d8d87818110151561039257fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff166103e0565b95506103c085826104b7565b94505b600190930192610260565b50939a92995091975050505050505050565b60608060008451600101604051908082528060200260200182016040528015610413578160200160208202803883390190505b509150600090505b845181101561047657848181518110151561043257fe5b90602001906020020151828281518110151561044a57fe5b73ffffffffffffffffffffffffffffffffffffffff90921660209283029091019091015260010161041b565b8382600184510381518110151561048957fe5b73ffffffffffffffffffffffffffffffffffffffff9290921660209283029190910190910152509392505050565b606080600084516001016040519080825280602002602001820160405280156104ea578160200160208202803883390190505b509150600090505b845181101561053357848181518110151561050957fe5b90602001906020020151828281518110151561052157fe5b602090810290910101526001016104f2565b8382600184510381518110151561054657fe5b60209081029190910101525093925050505600a165627a7a7230582056d78ee4f7397a0950a3692a9e267500e619b5d3eb5937b9142689bc9ee137f10029",
|
||||
"eip100bTransition": 20,
|
||||
"difficultyBombDelays": {
|
||||
"20": 3000000
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"params": {
|
||||
"gasLimitBoundDivisor": "0x0400",
|
||||
"registrar": "0x0000000000000000000000000000000000000000",
|
||||
"accountStartNonce": "0x00",
|
||||
"maximumExtraDataSize": "0x20",
|
||||
"minGasLimit": "0x1388",
|
||||
"networkID": "0x1",
|
||||
"chainID": "0x0334",
|
||||
"maxCodeSize": 24576,
|
||||
"maxCodeSizeTransition": 10,
|
||||
"eip150Transition": 0,
|
||||
"eip160Transition": 10,
|
||||
"eip161abcTransition": 10,
|
||||
"eip161dTransition": 10,
|
||||
"eip155Transition": 10,
|
||||
"eip98Transition": "0xffffffffffffffff",
|
||||
"eip140Transition": 20,
|
||||
"eip211Transition": 20,
|
||||
"eip214Transition": 20,
|
||||
"eip658Transition": 20
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
"ethereum": {
|
||||
"nonce": "0x0000000000000000",
|
||||
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
},
|
||||
"difficulty": "0x080000",
|
||||
"author": "0xc3F70b10CE5EC4aA47ce44Eb0B7900A883cd45Dd",
|
||||
"timestamp": "0x5a939845",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"extraData": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"gasLimit": "0x09eb100",
|
||||
"stateRoot": "0x2255c10db0a0f392ca63b1a3ca149e226f6bbf195c04a6ce4a077f9f02ffbace"
|
||||
},
|
||||
"nodes": [
|
||||
"enode://ab0d9fe81f23653c3217303d3a4bc035be908b05f8b12d6f155ab4598d7760cfea1e009e414771279c9ffc3499950283afaabe099a5329c5a6013f57d77de0a6@104.236.96.118:30303",
|
||||
"enode://9e2d9dc2639e02893aa17c80e6ba8e8803fd3166083b622a841fc852161112720281514436f7605c89041d5efa1738215185c4c4024ff812b0f500c403cc0ab1@206.189.47.198:30303",
|
||||
"enode://149ba679e8851c3e0d030e0dc0336984b97c83ef649e68ec113dcf266449364cc1ec8ee27950f71b00c2182ef504894fa7bff19f6741978ced67e9e4b6536d2a@206.189.45.31:30303",
|
||||
"enode://eeb3b1680f651b291a19454345721b5196a2a689dcd280e5f66dc3207636366d4b25e84d205303c2f8aa0a38467dad9e6f2536e195a4760df56aeac428ebea0b@199.247.18.157:30303",
|
||||
"enode://eeb3b1680f651b291a19454345721b5196a2a689dcd280e5f66dc3207636366d4b25e84d205303c2f8aa0a38467dad9e6f2536e195a4760df56aeac428ebea0b@199.247.18.157:30303",
|
||||
"enode://c21418c02f5ba480d64fbdf3dd7e1a276cbea441f9d55b8bb1c653fa3a05cc07e32a332f63df53f51d275dadc9b50925375a699dd39bdad991594326d6b8afab@199.247.3.3:30303",
|
||||
"enode://40aa8ff2c3d98ffc12004cb6a3636e7c9b79400153667163cfc24123f2ee3ee693ac45775183f5f6a7e315a4884899ac32ef0616e26cdd23a7b00f80d07cdeae@45.32.126.82:30303",
|
||||
"enode://3beb80913887d985a857076621baca66ea27b62ff159c5a41243d02a8614f537003c03ba1fe082b63a47e7f6f7ba1caf6bb14343560dbff6ba1e456e99e6119d@144.202.73.111:30303",
|
||||
"enode://b79a50393b16b76a6c94d7ddae80c44464c9e5ecc59fc2b7e83d0c248190de781e7e2aebeab8d466b3869677e6388e6fac8bd36f3925cbeebbe4cf0372a7eac1@207.148.31.238:30303"
|
||||
],
|
||||
"accounts": {
|
||||
"0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
|
||||
"0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
|
||||
"0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
|
||||
"0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
|
||||
"0000000000000000000000000000000000000005": { "balance": "1", "builtin": { "name": "modexp", "activate_at": 20, "pricing": { "modexp": { "divisor": 20 } } } },
|
||||
"0000000000000000000000000000000000000006": { "balance": "1", "builtin": { "name": "alt_bn128_add", "activate_at": 20, "pricing": { "linear": { "base": 500, "word": 0 } } } },
|
||||
"0000000000000000000000000000000000000007": { "balance": "1", "builtin": { "name": "alt_bn128_mul", "activate_at": 20, "pricing": { "linear": { "base": 40000, "word": 0 } } } },
|
||||
"0000000000000000000000000000000000000008": { "balance": "1", "builtin": { "name": "alt_bn128_pairing", "activate_at": 20, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } },
|
||||
"183394f52b2c8c034835edba3bcececa6f60b5a8": {
|
||||
"balance": "100491852286952719463755404"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3068,17 +3068,18 @@
|
||||
]
|
||||
},
|
||||
"nodes": [
|
||||
"enode://e809c4a2fec7daed400e5e28564e23693b23b2cc5a019b612505631bbe7b9ccf709c1796d2a3d29ef2b045f210caf51e3c4f5b6d3587d43ad5d6397526fa6179@174.112.32.157:30303",
|
||||
"enode://6e538e7c1280f0a31ff08b382db5302480f775480b8e68f8febca0ceff81e4b19153c6f8bf60313b93bef2cc34d34e1df41317de0ce613a201d1660a788a03e2@52.206.67.235:30303",
|
||||
"enode://efd48ad0879eeb7f9cb5e50f33f7bc21e805a72e90361f145baaa22dd75d111e7cd9c93f1b7060dcb30aa1b3e620269336dbf32339fea4c18925a4c15fe642df@18.205.66.229:30303",
|
||||
"enode://5fbfb426fbb46f8b8c1bd3dd140f5b511da558cd37d60844b525909ab82e13a25ee722293c829e52cb65c2305b1637fa9a2ea4d6634a224d5f400bfe244ac0de@162.243.55.45:30303",
|
||||
"enode://42d8f29d1db5f4b2947cd5c3d76c6d0d3697e6b9b3430c3d41e46b4bb77655433aeedc25d4b4ea9d8214b6a43008ba67199374a9b53633301bca0cd20c6928ab@104.155.176.151:30303",
|
||||
"enode://814920f1ec9510aa9ea1c8f79d8b6e6a462045f09caa2ae4055b0f34f7416fca6facd3dd45f1cf1673c0209e0503f02776b8ff94020e98b6679a0dc561b4eba0@104.154.136.117:30303",
|
||||
"enode://72e445f4e89c0f476d404bc40478b0df83a5b500d2d2e850e08eb1af0cd464ab86db6160d0fde64bd77d5f0d33507ae19035671b3c74fec126d6e28787669740@104.198.71.200:30303",
|
||||
"enode://39abab9d2a41f53298c0c9dc6bbca57b0840c3ba9dccf42aa27316addc1b7e56ade32a0a9f7f52d6c5db4fe74d8824bcedfeaecf1a4e533cacb71cf8100a9442@144.76.238.49:30303",
|
||||
"enode://f50e675a34f471af2438b921914b5f06499c7438f3146f6b8936f1faeb50b8a91d0d0c24fb05a66f05865cd58c24da3e664d0def806172ddd0d4c5bdbf37747e@144.76.238.49:30306",
|
||||
"enode://83b33409349ffa25e150555f7b4f8deebc68f3d34d782129dc3c8ba07b880c209310a4191e1725f2f6bef59bce9452d821111eaa786deab08a7e6551fca41f4f@159.89.223.6:30303",
|
||||
"enode://5cd218959f8263bc3721d7789070806b0adff1a0ed3f95ec886fb469f9362c7507e3b32b256550b9a7964a23a938e8d42d45a0c34b332bfebc54b29081e83b93@35.187.57.94:30303",
|
||||
"enode://6dd3ac8147fa82e46837ec8c3223d69ac24bcdbab04b036a3705c14f3a02e968f7f1adfcdb002aacec2db46e625c04bf8b5a1f85bb2d40a479b3cc9d45a444af@104.237.131.102:30303"
|
||||
"enode://6dd3ac8147fa82e46837ec8c3223d69ac24bcdbab04b036a3705c14f3a02e968f7f1adfcdb002aacec2db46e625c04bf8b5a1f85bb2d40a479b3cc9d45a444af@104.237.131.102:30303",
|
||||
"enode://b9e893ea9cb4537f4fed154233005ae61b441cd0ecd980136138c304fefac194c25a16b73dac05fc66a4198d0c15dd0f33af99b411882c68a019dfa6bb703b9d@18.130.93.66:30303",
|
||||
"enode://3fe9705a02487baea45c1ffebfa4d84819f5f1e68a0dbc18031553242a6a08e39499b61e361a52c2a92f9553efd63763f6fdd34692be0d4ba6823bb2fc346009@178.62.238.75:30303",
|
||||
"enode://d50facc65e46bda6ff594b6e95491efa16e067de41ae96571d9f3cb853d538c44864496fa5e4df10115f02bbbaf47853f932e110a44c89227da7c30e96840596@188.166.163.187:30303",
|
||||
"enode://a0d5c589dc02d008fe4237da9877a5f1daedee0227ab612677eabe323520f003eb5e311af335de9f7964c2092bbc2b3b7ab1cce5a074d8346959f0868b4e366e@46.101.78.44:30303",
|
||||
"enode://c071d96b0c0f13006feae3977fb1b3c2f62caedf643df9a3655bc1b60f777f05e69a4e58bf3547bb299210092764c56df1e08380e91265baa845dca8bc0a71da@68.183.99.5:30303",
|
||||
"enode://83b33409349ffa25e150555f7b4f8deebc68f3d34d782129dc3c8ba07b880c209310a4191e1725f2f6bef59bce9452d821111eaa786deab08a7e6551fca41f4f@206.189.68.191:30303",
|
||||
"enode://0daae2a30f2c73b0b257746587136efb8e3479496f7ea1e943eeb9a663b72dd04582f699f7010ee02c57fc45d1f09568c20a9050ff937f9139e2973ddd98b87b@159.89.169.103:30303",
|
||||
"enode://50808461dd73b3d70537e4c1e5fafd1132b3a90f998399af9205f8889987d62096d4e853813562dd43e7270a71c9d9d4e4dd73a534fdb22fbac98c389c1a7362@178.128.55.119:30303",
|
||||
"enode://5cd218959f8263bc3721d7789070806b0adff1a0ed3f95ec886fb469f9362c7507e3b32b256550b9a7964a23a938e8d42d45a0c34b332bfebc54b29081e83b93@35.187.57.94:30303"
|
||||
],
|
||||
"accounts": {
|
||||
"0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
{
|
||||
"name": "Byzantium (Test)",
|
||||
"name": "Constantinople (test)",
|
||||
"engine": {
|
||||
"Ethash": {
|
||||
"params": {
|
||||
"minimumDifficulty": "0x020000",
|
||||
"difficultyBoundDivisor": "0x0800",
|
||||
"durationLimit": "0x0d",
|
||||
"blockReward": "0x29A2241AF62C0000",
|
||||
"blockReward": "0x1BC16D674EC80000",
|
||||
"homesteadTransition": "0x0",
|
||||
"eip100bTransition": "0x0",
|
||||
"difficultyBombDelays": {
|
||||
"0": 3000000
|
||||
"0": 5000000
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,11 +30,13 @@
|
||||
"eip161abcTransition": "0x0",
|
||||
"eip161dTransition": "0x0",
|
||||
"eip140Transition": "0x0",
|
||||
"eip210Transition": "0x0",
|
||||
"eip211Transition": "0x0",
|
||||
"eip214Transition": "0x0",
|
||||
"eip155Transition": "0x0",
|
||||
"eip658Transition": "0x0",
|
||||
"eip145Transition": "0x0",
|
||||
"eip1014Transition": "0x0",
|
||||
"eip1052Transition": "0x0",
|
||||
"eip1283Transition": "0x0"
|
||||
},
|
||||
"genesis": {
|
||||
@@ -56,9 +58,9 @@
|
||||
"0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
|
||||
"0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
|
||||
"0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
|
||||
"0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 100 } } } },
|
||||
"0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 20 } } } },
|
||||
"0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0x00", "pricing": { "linear": { "base": 500, "word": 0 } } } },
|
||||
"0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x00", "pricing": { "linear": { "base": 2000, "word": 0 } } } },
|
||||
"0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x00", "pricing": { "linear": { "base": 40000, "word": 0 } } } },
|
||||
"0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x00", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }
|
||||
}
|
||||
}
|
||||
|
||||
54
ethcore/res/ethereum/eip210_test.json
Normal file
54
ethcore/res/ethereum/eip210_test.json
Normal file
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"name": "EIP210 (test)",
|
||||
"engine": {
|
||||
"Ethash": {
|
||||
"params": {
|
||||
"minimumDifficulty": "0x020000",
|
||||
"difficultyBoundDivisor": "0x0800",
|
||||
"durationLimit": "0x0d",
|
||||
"blockReward": "0x4563918244F40000",
|
||||
"homesteadTransition": "0x0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"params": {
|
||||
"gasLimitBoundDivisor": "0x0400",
|
||||
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||
"accountStartNonce": "0x00",
|
||||
"maximumExtraDataSize": "0x20",
|
||||
"minGasLimit": "0x1388",
|
||||
"networkID" : "0x1",
|
||||
"maxCodeSize": 24576,
|
||||
"maxCodeSizeTransition": "0x0",
|
||||
"eip98Transition": "0xffffffffffffffff",
|
||||
"eip150Transition": "0x0",
|
||||
"eip160Transition": "0x0",
|
||||
"eip161abcTransition": "0x0",
|
||||
"eip161dTransition": "0x0",
|
||||
"eip210Transition": "0x0"
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
"ethereum": {
|
||||
"nonce": "0x0000000000000042",
|
||||
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
},
|
||||
"difficulty": "0x400000000",
|
||||
"author": "0x0000000000000000000000000000000000000000",
|
||||
"timestamp": "0x00",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
|
||||
"gasLimit": "0x1388"
|
||||
},
|
||||
"accounts": {
|
||||
"0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
|
||||
"0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
|
||||
"0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
|
||||
"0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
|
||||
"0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 100 } } } },
|
||||
"0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0x00", "pricing": { "linear": { "base": 500, "word": 0 } } } },
|
||||
"0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x00", "pricing": { "linear": { "base": 2000, "word": 0 } } } },
|
||||
"0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x00", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"name": "Kovan",
|
||||
"name": "Kovan Testnet",
|
||||
"dataDir": "kovan",
|
||||
"engine": {
|
||||
"authorityRound": {
|
||||
"params": {
|
||||
"stepDuration": "4",
|
||||
"stepDuration": "0x4",
|
||||
"blockReward": "0x4563918244F40000",
|
||||
"validators" : {
|
||||
"list": [
|
||||
@@ -19,10 +19,10 @@
|
||||
"0x00a0a24b9f0e5ec7aa4c7389b8302fd0123194de"
|
||||
]
|
||||
},
|
||||
"validateScoreTransition": 4301764,
|
||||
"validateStepTransition": 1500000,
|
||||
"maximumUncleCountTransition": 5067000,
|
||||
"maximumUncleCount": 0
|
||||
"validateScoreTransition": "0x41a3c4",
|
||||
"validateStepTransition": "0x16e360",
|
||||
"maximumUncleCountTransition": "0x4d50f8",
|
||||
"maximumUncleCount": "0x0"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -32,18 +32,26 @@
|
||||
"maximumExtraDataSize": "0x20",
|
||||
"minGasLimit": "0x1388",
|
||||
"networkID" : "0x2A",
|
||||
"forkBlock": 4297256,
|
||||
"forkCanonHash": "0x0a66d93c2f727dca618fabaf70c39b37018c73d78b939d8b11efbbd09034778f",
|
||||
"eip155Transition": 1000000,
|
||||
"maxCodeSize": 24576,
|
||||
"maxCodeSizeTransition": 6600000,
|
||||
"validateChainIdTransition": 1000000,
|
||||
"validateReceiptsTransition" : 1000000,
|
||||
"eip140Transition": 5067000,
|
||||
"eip211Transition": 5067000,
|
||||
"eip214Transition": 5067000,
|
||||
"eip658Transition": 5067000,
|
||||
"wasmActivationTransition": 6600000
|
||||
"forkBlock": "0x9766dc",
|
||||
"forkCanonHash": "0xf2fa4bcc417ad374100c2035aa865ff60fb568a83db1b6f6cb8fb52cfebc28b5",
|
||||
"eip155Transition": "0xf4240",
|
||||
"maxCodeSize": "0x6000",
|
||||
"maxCodeSizeTransition": "0x64b540",
|
||||
"validateChainIdTransition": "0xf4240",
|
||||
"validateReceiptsTransition": "0xf4240",
|
||||
"eip98Transition": "0x0",
|
||||
"eip140Transition": "0x4d50f8",
|
||||
"eip211Transition": "0x4d50f8",
|
||||
"eip214Transition": "0x4d50f8",
|
||||
"eip658Transition": "0x4d50f8",
|
||||
"wasmActivationTransition": "0x64b540",
|
||||
"eip145Transition": "0x8c6180",
|
||||
"eip1014Transition": "0x8c6180",
|
||||
"eip1052Transition": "0x8c6180",
|
||||
"eip1283Transition": "0x8c6180",
|
||||
"eip1283DisableTransition": "0x9c7b61",
|
||||
"kip4Transition": "0x8c6180",
|
||||
"kip6Transition": "0x8c6180"
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
@@ -56,8 +64,8 @@
|
||||
"gasLimit": "0x5B8D80"
|
||||
},
|
||||
"hardcodedSync": {
|
||||
"header": "f9023ea00861b3771ffb84fce48b8ba3c54a09f81e91ccb38c401261f06d370098889a43a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479400e6d2b931f55a3f1701c7389d592a7778897879a071cc81d58cdd21d1e17f7389e55c530cd9f94cc15bb32af6477320682327dcffa06090021a7c09ae5e75e443410ebdb76de04f1eafb0ab910daae96ee6eec560eaa032510bf257dd03b11f3b4761b94b495a5b5a18cd6eb17c77785e0f46e2ffc882b901000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000400000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffd8381e001837a12008306697a845b83bd6096d583010b068650617269747986312e32372e30826c698416e0ef58b841117e2088e2835bf2afcd5d48f42b3bf2a1f33435f21f089ead2a6bae7d01c1486e645b460bb3c726a827ff1eb50e0579f3410563bae090fc256cf1d8d594b82100",
|
||||
"totalDifficulty": "2845866505151538604560067685603735513869853136",
|
||||
"header": "f90247a0017c9292a6abf6bb9aa48c30f8854dc0e9649bceaf19079b1aac50ebea4fa316a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794007733a1fe69cf3f2cf989f81c7b4cac1693387aa06b81f6633226562f466201f0d097877c903a650f7427aefa7433fb971f601287a0098141509099d91ed2c2e503d43db5b5412d51880994e8e03a86e1d7a9ca8e8ca0495f318f8bfdd4beb517d115ad5d5330aebafe70eb2b1cfb0ab029221a0f48c1b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffe83975801837a120083035108845c2c49e49fde830202058f5061726974792d457468657265756d86312e33312e30826c6984170b1279b8413ee0655a59d1f7f8db39c22055c614346450e99965fef62efa43b21b20f0966e3e41eb65fcaf6f9ce3a34359dc064827e06f3a29d2c717f287234785d369e56f00",
|
||||
"totalDifficulty": "3324635628632492920129912637269655024947201711",
|
||||
"CHTs": [
|
||||
"0xdb9557458495268ddd69409fc1f66631ed5ff9bf6c479be6eabe5d83a460acac",
|
||||
"0xd413800c22172be6e0b7a36348c90098955991f119ddad32c5b928e8db4deb02",
|
||||
@@ -4214,25 +4222,801 @@
|
||||
"0x3ef50c81169af169c100f58f3afcb8e2f926d957b2adbaca8787be5d4e8d7233",
|
||||
"0x8783eaeb56ca2d7fec84e0e272b77271fdfd6c14452a2e1dd83de770c5d99a1a",
|
||||
"0x861024460895378ba100c5d0c05e62bb6cac8b21ae529ab5cab39eb6c6cabd90",
|
||||
"0x1c741ed9eda60e5ac585e2f48f06fb988367c2c40a0d8111bb04b260fe44ec6b"
|
||||
"0x1c741ed9eda60e5ac585e2f48f06fb988367c2c40a0d8111bb04b260fe44ec6b",
|
||||
"0x6051d77e0596a911bce132c4bc12be2ae5cf29d113dd52a41b3bc166861149ce",
|
||||
"0x92c049df5ddb238644015d4e039e169614ed1d926de070952f2407912906cb4b",
|
||||
"0xa897567fc1ee9437f2876deb3de2b11b8fc00aa07340564031573f0351ec556d",
|
||||
"0x3e54a8e15218db168960d28369003cdb1a76f8db19384e9e2696ae66a6693d6e",
|
||||
"0xc5db7ade97cf28f8b61f2c63a0773201ba64f37dadc19c03943b6772aa7a1a50",
|
||||
"0xda784d1bf64b7efd06558b90cd2436f3e61dc0f7a8370ff92516ed062f461091",
|
||||
"0xa1d10b0a36ec5169d2df740878d051bf4d38ebc5dc04ae5558daaabc2bfa1471",
|
||||
"0xcc89a8be2ff74a7bb9e967cfea3cac067aa84cc455a2fdd5449577b52a2b4ff3",
|
||||
"0xbd23a3e6d3198d81d798c2851c36b954fa6f359bc8fc6e04a0b757e3d0ba053a",
|
||||
"0x74640f825b9d9f95be69763845aaa0269d3a6ed5aaec88bfd9b5c4139ba7ef41",
|
||||
"0xc01a29e41af3cc0d0a13ea83f131f3e4828ec3e83dd2fdf9739c139938dfc2b3",
|
||||
"0x832509e705972acc7efe91475e8d76ac00a12750e194847093825e6c4db9e83b",
|
||||
"0x63139d1224766ada1318613b9ec5894308efa2473e809d9e37c8305c6965f2cc",
|
||||
"0x76547e54dc59473093c3fcca1166307cc7d0f4f0e8a35d850507bec216b76476",
|
||||
"0x3a6a14785272391982cfa690762f5b2aeccc1dc0bb13eab6b9fcfd056f40703a",
|
||||
"0x603e32b52795c04416d800b6a936343aaaa09898fa97cadc2b157eeaaf3bd6f7",
|
||||
"0xf241102a3d3f3a9fdc5a1a586b16fdce4280c6c6da04290541eb3cb9c28c7325",
|
||||
"0x6db6de041bcc7c00104a21bbd487a1e1ddd5e4953f7a503aa992d68a8a7bbc43",
|
||||
"0x8377d795c55eac07c0acca674e775ed7d8eea35867990c8a776f40965c9ddc68",
|
||||
"0x48d62d562279641043e405f4d7fbd76050d773103871c5de2c8acc25992db502",
|
||||
"0xa9ef42d314e15c419537e022753ab46d41318f1fa8784e4363494f395eb6d236",
|
||||
"0x99572f567eb602a1d9839bd23b41562bb3782eccf9a8893e54b002e685ab378c",
|
||||
"0xd8cf2fa2291efed46c1a36e1b8837be62e86caacc380aa6397792ae8baf8f3a1",
|
||||
"0xed2e800df1acb7bba5ee6251592c397a604debd7b0bfc28c8b0002dc40faa8bf",
|
||||
"0x9ccece195d9e67e318f6d2952bca9486d09f4207c6d8be266cc0eebe41290920",
|
||||
"0xb20580a5c96c25bb59e1bae6ced3ea5cb69d903f64e648bcb38b799141b3cd5b",
|
||||
"0x1488647e697452306d2744ca6c709007cf75e2e37da3c7c05006211ba0720824",
|
||||
"0x009c3dfc5494962c77900fb8da67d7bf2a2f4b855c521b9d50c4aafb1e0735bb",
|
||||
"0x482428835dfff3ee1da335b36ba3aa1969fa35e89150e5b3c1991f28272d14f5",
|
||||
"0x6a972044f2076e98833b243c9ed18162d96b46823170ef7c20b1a02d8bbd48c5",
|
||||
"0x676242effe0fae84110c4933beecfe5ff549b439e54ff5a588add229329e5365",
|
||||
"0x2441bce77589ebf8019fa8ae870a8529479c6eaa0fed7e0fbd3cc7439dbd4a09",
|
||||
"0x0b20c25d2c6897c1a8dc9ea1364d3c72d33c97b4d70b9176c3f0a1e3b6ce08a7",
|
||||
"0x685aa4e279118f8326a90c78e9896e40d9baa62144e2425887dcc704106979c3",
|
||||
"0xabcab60973f6bc9ec3b596452e7434c4dc89c55c8eea925fc0092d1103c6f86b",
|
||||
"0xcbf44f106f3f2c0050906b5e344ad22f0e0034067d35402d447311d254516dd0",
|
||||
"0xcaa67796a8ac69283d7b6304181a988992130ad8441d47b4fdaf236686dc1caa",
|
||||
"0xad06e6db230bd0bfaa0df59d1ae517ced29d5f11b34f76ef9bb6a73407128b59",
|
||||
"0x93ef56a4951e4e5c19230918b1219c1f07e9356363503c1410e71486ed338f87",
|
||||
"0xc6fef02b5bdd4909906c40cf5b999fe9e08e4c0d8bfe59d3c9aa99011136f780",
|
||||
"0xfed633749700ffdeb0921a537a215ae31c25b85e4f80727376e50c247b4c5a38",
|
||||
"0xc39d8cc15f4331fb7db2c24ee1163bd164e81ad2ebc43271f841fb25d03835c6",
|
||||
"0xb13962dcb364ee49e2d0a34dd1a555fa8df363041504ef1e987ce78646d64146",
|
||||
"0x97e0d3047e2151d53cbd1358da627453558362c6a830910b33f241848b20cffc",
|
||||
"0x587ea98cbd1da50c0af1986f6ee5e676658c06442e893304708db831fec8e804",
|
||||
"0x0a1d21212d9bd85a1a39e046c897d1dafb496bfd80762beda2fd3eb1cdc72eb9",
|
||||
"0x46aad83612f04e7a51fd642de742f713601992e58de4daf24148a3e6f3318aa2",
|
||||
"0xa65a8a9ed4fb28fcab6ee3af5df4647083c2e735fc652568759fe0426e9a294e",
|
||||
"0xacd7ed5525cad187f053ba98487cc4abf24f76c8c0e97e71a696d553a3a41b7f",
|
||||
"0xdcbdcfbaee764bb404bfa5261b5037b9c7ce567a3c1aa9f7280071990320da18",
|
||||
"0xf195aae79a232b2170a98602efaa2efbdebb3c40d2438e63bf0954e4dc779cb0",
|
||||
"0xfbb2675a62e2e67baf85e56fcd4cdf2bf89ff7905952155d3cfd4e625fb674d9",
|
||||
"0x5b955473a35f6b0d24fa8be8009734ecee62f6c4bcf0cafc2335f07c51752fb1",
|
||||
"0x66f37b268338f4ba1e21eef6884aef245bc36935be1f5eb14ee1d23618f00f5b",
|
||||
"0xaab809ee86773263043201b83bd445d98a634d8a6da4c389b2336f68381dd481",
|
||||
"0x509fc38118491458e45c7e8ab1d60c687f50d85fc1c0bf104b531a3b352198ea",
|
||||
"0x20d1e4f38e83b27b77d55281af40e9f96be098fdbb90730170638c88ab7e435a",
|
||||
"0xb33711864d62709a98f81d9c5f0a301bd5808d0e8ecef1063c97347af754c8c2",
|
||||
"0xd69fd6c0fea478bb380b948f5b054f91831cf26d304991d40ebdf0b00a97503c",
|
||||
"0x87157d452bf57e617ac1dd2372438b0777b83f6087d8223008d823652c634882",
|
||||
"0x9c54b0172ae0223e6b23f7e000cb6887144e615efb02c74596002dc26d43eb5c",
|
||||
"0x5b0f87baa8e40f0a2bbc1a76afbe0b21b5e8aae1443f0d38c3ac55c5f942db42",
|
||||
"0xeb68d93e19860fb9fb76847080edc345972e29ab1ffd417ae5727d3cec79c0eb",
|
||||
"0xd27026033bba2557c79c4babaf669a399fbc72a2a5cc06c707e24eaacee83bce",
|
||||
"0x420d887bd82cccac29711c52f4d362b6a7d854e694f8d597d208d0a094fbad8e",
|
||||
"0x02ff085c6c3c47879a91f511ea4c54a214af8160e07dce8e82a6be9e8299e237",
|
||||
"0x1f0384e0afaf47ba59aff9f224905950768674c48de0fb0312749b16edb0a347",
|
||||
"0x55cefaac814e132ff335882a366ea6173bc21fa713e93d8ad92260c84cfd2d85",
|
||||
"0x58a8dd6e036a05a937a7053be916c0e7f719f2a1905186e7586a9d2dafd5a1a4",
|
||||
"0x8714d03549461e32a467cefdad60a96788c97172db05c18eb9debf6e6a4d39e8",
|
||||
"0xd141656c1f57c12feed31dbff3817e1d2af4e1b5cf6aa75d1bb29ea2c0a3ae69",
|
||||
"0x5ec365177e19fca3c1063e65a9342008aff04ba9d03d53837b598b143504b97a",
|
||||
"0xc620e23ae73d423bf2628a3de70b1a1f915d80173e0c8d1443a44b91400c5a8a",
|
||||
"0xc72c2356ed53eae5a4a56bc248d9d2f4e9154f1404780b84781f357cbc7ad2d2",
|
||||
"0xe60bfe30e5a1a9457ccca65810675e129948b474f391ce64d270200be7ea6beb",
|
||||
"0xf679887baad8f8e497d60b015156f194b94fc30c6cb1f83fbc4575e99b95a8d5",
|
||||
"0x654463146799fcfa18a74ffe4f2423fa04c8747c16b789dd24da26d0338d381c",
|
||||
"0xe8b5406278d9e4622d088976af8b5e6b14cc146a9530c862a42fa5566a247355",
|
||||
"0x8ecb4735132f769663781f96fb531115190e68390c54e33b250db874e90aebaa",
|
||||
"0xef13bf38c2ba993c9dea5777e5db348339273d0e6dd1f41867d3b258f24ac4d4",
|
||||
"0xbbbbeedf7276a857c513f4ebce88e3b531c99cf206eacd1c6c29d3cabab45df4",
|
||||
"0x89cd50cde2de3ef40de7502241b78e664de53dd4a5e2ed85db62c55be0a4d8a4",
|
||||
"0x0da2cae061e7dff539c7e39b0b9f63af3217f1a51bc597db957b6a3972cf7186",
|
||||
"0x57aa87a6daab3c65519de7c1c1360ab33b830d46f169d4e0d3c38e7dadef289b",
|
||||
"0x85fb1241c4110b4f3a6c197450af8ac47bb24d531219f6cefcc079717b208c84",
|
||||
"0x52194cfba6bd7d5eb8b438054fbaf5fef387cdb8b1a7ebafe44cdcf4da47b1dd",
|
||||
"0x7d24eb47a1310f7f4244e825847f634fd4a4224f695a3609c5250dc6052de6d4",
|
||||
"0x38edeacb93b10653624f77dc05063499daa770b74d6b63ebe656be5a3630b7b8",
|
||||
"0x4e050f7b9d73c1aea3ce60c8eae8e46b55b6d4c1cd1eae22faf982895871dcd1",
|
||||
"0xf22b284ed4d97b7d3553600388748721a328052daaf92a58ed5403fd4020a496",
|
||||
"0xc5fcf858d9a9748045fa0ca1271ba5af780a788c51d693815e0490671be3885b",
|
||||
"0x2342efdb88226e68173ef84060a0d4dc6c8aa9c9431883beef4a5588f3157fae",
|
||||
"0xe1599bf452eaacb8dcd51ff835a9ef5761dbce83cfc719813d6a10772ca5fdb3",
|
||||
"0xb754797393b3216778ea6389361ca5951f365ae4e7ed99ed4cd4c9c76ff442d3",
|
||||
"0x3fb5f9f3754764155296c6ff4c469109512264c603ece7c78c1231942bb8ac35",
|
||||
"0xbb347d23c7d703cd2801e2763f1a6c375b5cb2a666ba137c4d6442c3f94688dc",
|
||||
"0xed3806645b55fd7027dfb7f5f796933049ae558d26ca695a01e1b11333f5e453",
|
||||
"0xeadb7740432ede4f90c0bc490c15fb377b68de0fc1ee3a56e87e21e7771211fe",
|
||||
"0xa8c0e907e0b544e7fc3116d47e4cdfc8e8688f5cc4a67cdf600f74be6b79775a",
|
||||
"0xc6f6b94f2fb4c56066e3c722123b8e85f80ce8baa0427b62c5a2ff937702c481",
|
||||
"0xfff0b94553a7daaee58a7e15daf9845d1a3ad4917d81d4f23dad27d0262b48ec",
|
||||
"0xb9084676613e1a063c2b491bef1b984acfbd2dce60a8ed970688239524e31962",
|
||||
"0x196af717eab2cf09b47db13605ca4864cb0c4189d40c9b618d8a7d3f92831d78",
|
||||
"0x4fac369653dcfe74d86b7422354d68f7580b1ae0ab359a8b8f8be8582590ea7a",
|
||||
"0x035ff04f84478354706945480266321d31790f5445028f3e964801fd9a16c78c",
|
||||
"0x63df70a24370a408bffabbe1c7a4c9b9e40be1cb326ab10d63fe54bb9de50d34",
|
||||
"0x37b5c558d31128595425ca68deddf5ae7539abc6da838837eb1e0457e092d9ea",
|
||||
"0x41a9ce82ab27afbc84669368c2e75a15e6386b77034ec316795a896ef9de577d",
|
||||
"0x08bc6cc18842df4130280823f7676f418f4797d3ddfc544e54267e6456cfac68",
|
||||
"0xeabc09ffceeb35cc4ec18518d4920bea2f43bf746f23b5524fa405bd874e9d34",
|
||||
"0x40336744dcfe6f312e17eea83f53538f9999864c41bec43576cfcbef68d12e7d",
|
||||
"0x3e780dc9c8f2b708527f1eebca75d18507e00e226a00e1b1ddd0b715aa8dd561",
|
||||
"0xfd6a3c50c4a4d6e1a6fe27fa96f6aa2654573cbb9b839ce8e09a75993e2bf8e5",
|
||||
"0x166c03d381d6ab94666099024adc95de0ecc9818e5ceb49965767682ca0c73fe",
|
||||
"0x9805810b802a51a3ae18ce44f6b2c68abfccef2119df2430e4693e291059e222",
|
||||
"0x353ecd1a0922e819ffdcd634385ebbdb674d247c4fe75e2d5437b659c98424a4",
|
||||
"0xe75fb8682b706ed6596699d6151db4dcb19f6e71a3b6e34aabc3508c919f5c17",
|
||||
"0x6e9bab64b10a2341f49e81d862ef3322d3117842e3f1aabc8b774c68484a2a31",
|
||||
"0x82b5e79ee8d72c3613458c975530bcbba359734a4e9f07015686dfc521230329",
|
||||
"0x86d48d57ccbe1f1986a4043748b1a0d8d76fd56bc74e7c48c6fd742affa0ee11",
|
||||
"0x46ee65b9c2fa3e69aa1cd6ba5aaafa7f7aef59224098b60e22994996c927c9c4",
|
||||
"0xb6983761b177e21899799410dc018f1acd3d417fe35943fbe57207f9f799a100",
|
||||
"0x594057a8386db6e159d43d136c464c5e3980eae75a73900f7a84ba94803fc6c4",
|
||||
"0x53c78073c4a4c44d17db85be06f38ab47ecbb7f36ffa87b9db707fd2bc87f391",
|
||||
"0x4a976673044732e3e8a0987fc8f3c36375e3c4fb3722fcde5259af492ec458c7",
|
||||
"0x1e2fc8db341a4d9e123ae4ff4f4d8096d8afef47c5d2915c665922bd1de3b00c",
|
||||
"0x565cd8eb410c6e0b4d67b54d37ff42f6189095965896b0f81566ca502bea34e3",
|
||||
"0x32d030e4ff6b2f5a560cb7525b5e66ab1f34a1e06531f9b81c48b8a257bd5637",
|
||||
"0x25a91d756023bb9ae538034bd39b6e698d05fb1393d1328c4fc7e5c14209cce1",
|
||||
"0x8036f74c4cbaff3bd98820ddd84bc093c95e88d357b341154a3189715225d068",
|
||||
"0x8bc6bc61f7a57a145b8d728f583e027c8630f0c07e003b189f390ffd11d6f150",
|
||||
"0xfbeb53fa167d067c9b0a2c0710f7f5931484f7dd90b9456c52c578a15f402d9b",
|
||||
"0x8d355b208a16b8aa3f7bc5d8864dc7d6a1c4917a97c523274b86e82998d60b63",
|
||||
"0xc94e45da800d7b56456d55a9aa36ddf9df45e9cfeeacb1116b8c51a0cea34ebd",
|
||||
"0x81761ec04a8d219aedb2f58aee529e876043b0a476e771957bc03fef9f0780de",
|
||||
"0x29264094c720151f7448cae053a403aa86fc20649bcf383517e214d1677e893e",
|
||||
"0x9ac97c7eef9b69dcd73ec7144a0cddfbf0973791beed405202fb4c2d932ec59e",
|
||||
"0x89611f8e2f9e2e1629f83ec14aaec1656876718c05088e5087887c87b8414c39",
|
||||
"0x67244fcdba97905472631378fa3a228b649880c2efdd57e5a6c95e9b70ad8456",
|
||||
"0x0d554cfc4df02560c3e76159d1964c69c39f5df9489bba5516f28a32a4be202e",
|
||||
"0xce9274a36a0f25a13edef679a5b286bf91a9dc5274354bb6f1ce0ac52557e650",
|
||||
"0x6017e68689d9f6dca78f42b93a224b445c18b70288a6e4c0d6cc295627dbb1b9",
|
||||
"0x76791c90f887355878d0a4d8c84ec3990a3159933ecc8d868d196b363153bd5f",
|
||||
"0xacb6a6c9ec937b3d5cedba26ab6d581fc41cf9a58b0867232e2c8c73d9978cc3",
|
||||
"0x89f17989ef556a0562c2aa5a2a1d71e5132b89d656bead1ef88ad31073b80cd1",
|
||||
"0x06efcf8dbadaf28ee719a5b9c017a093fde84a7f4b9966fe3052c0b2fe410ea6",
|
||||
"0xce16909616f1d97e5853818938b4798030259ddd41e3468f35b940ca901d6817",
|
||||
"0xd3ff9e9ad14a605a94bdf05dd2639b6fbda28ccf7b2b228f064b0de52410df5b",
|
||||
"0xb3e8ca9ee88d4c3ce347d82e8f22793ba22b7adc350fd694b1b00b0764c584f9",
|
||||
"0xe690268a4ec089aced00f9654aa95acb7a8d7270d9428205b103c30a08d142eb",
|
||||
"0xd685e1460799c51f14273361e31b9739e5212fa538fb8dfbb8e81e8b1d329bbe",
|
||||
"0x664c293680fb7c5a89ff3c31e81ec8d0c30a6274ef44e4e76bdb9bba83f3c0b3",
|
||||
"0x44027fd23526685d920d37b032f912159e308286eaac018244006690b4191d4e",
|
||||
"0x7ea934c3d75a9ecb6a2055dcd5feaf2d4c851eaf360a648d5d87ef40fba2fbd0",
|
||||
"0xfd97fc801315e5be630ccb3dc983c409a58fc1fc307adc1e4a48fc60c89ea40f",
|
||||
"0x15aa0c3c732a2c6684d521729dfeb93f62e22e155d85d20e5488e2c86b043142",
|
||||
"0xba235420ac54100da28cd6f30ff64b8594e73c42f45ca8494fb3d3c4d66651a9",
|
||||
"0x9948e8489cd94bed4b8e90a8bd35e01ffe38e7c077f587c6c1949caa99cc98e0",
|
||||
"0xcf66ccdfa85655d7d4c94cffd41f499afdfa2bbddcdaac547223e6ac4d1f9cf1",
|
||||
"0x7e5382881f710530720b420a3f3ac08211565ecc8fead8ec649cea11f9385c3d",
|
||||
"0x104576fbb1760c16ce85c3e5757832d53bda83d618500ef677a6a192ff14a5fb",
|
||||
"0x9e4689bb1ee34635e1106e38ca41833d2dbc1cfacb7635ede5761048a8637c7c",
|
||||
"0xc8c7f7ac271015da443320f4af650fc71ea0914f4c41252a5b7ec76f329d5268",
|
||||
"0x46a93ae992001a54119c8d27788e3ef8927dee0a9949b22ece0196a90932c1da",
|
||||
"0xa69467f9944f1a5e3a46718a99d3cb14930cab6d971baa37bb774cc757e55c2b",
|
||||
"0x33f7272fdbfb91428a1344df5867300e256fc3cc2e439c777c3feae1cb27b781",
|
||||
"0x0aaa367f4c7f399edc64ac1754f47aa5c28b0fa208238276de6bd9e424021ce3",
|
||||
"0xf5f363c3bfa4a23bf221951f4b53a77b27613938babe40f0832d05fdfd252233",
|
||||
"0xec315af99bdfdcb3cab1f1dcaa5b42ef53f4e3fcf4d921578892a5896fa20e9c",
|
||||
"0xb580a8e51e875446d7096a20801dded1f7e5b5fac9f47e9361dfc9dd80214013",
|
||||
"0xb877df38d8f4cebdfb89f26868bdb97ef945da187b44e1cbeafc1d4b7059d713",
|
||||
"0x78613b9d2d6b639a54ecf1d50a56af80560b436fa632ae636cf354d4a6dd4af8",
|
||||
"0x80a9d0a5e43558f1d24256baa6940c0074fa84d4b8e7e236054943f9ad5fbe2b",
|
||||
"0x60f79f699ba1a740c9784f2a8f1b652d4e695ad2d230b110472b95914fd35c8d",
|
||||
"0xae20de288eb7362a36a1ff236faaed6ddaacf58783d098118bc9fe66b8780651",
|
||||
"0xcd08003531d6094cabdbe4d971a01b41552784c246bd2a2f749ee9947d1394d6",
|
||||
"0x676720accf739c380f64748390c1acd2f88d454539866f7326a517c9b629b545",
|
||||
"0x086b71ac681c0ea369c16b22ca49753b2083ec25b46ba659206433eb060d98c3",
|
||||
"0x78910ab7d67e67da722ad53b669d8c3a312de3cf362c6254c09581088e920acb",
|
||||
"0x5bc6e98a830c114cb432091679ac5b3efd25c362d6f99585ce3a027dff95e524",
|
||||
"0x8d0daff5a97327b615d1535fea44fa33610fd645d93035e1e5e2bb49d4dcef24",
|
||||
"0xbb46662b884bc6676d98ebf3f2a35ff9190339b72d68520fe40100b4eafaa2a2",
|
||||
"0x9aa8faaf935c95a60ffae0487844860084a963792ae0bb90a831f825339810ac",
|
||||
"0xfd77b5d6b6b87bfb0ddcad7b0ed3992e5fe897b16db06b118230b2d292e317e9",
|
||||
"0xc465a3384c694bc50cbe97ce9f3bc364884651a97a491f7f64e65dc319d1c9f0",
|
||||
"0xc4634431867d7a302be79e83fb50d01df7f3b950aeede21fcb59b883399b06e4",
|
||||
"0xfd524c29525cb97a89026ff68048ca6e2a9f522791eadd74447a6c278151d7df",
|
||||
"0xc7df516c295a58cf4cd5614eee3d2f773a412dcd4926eadad7e935ecae6d8907",
|
||||
"0xfb915abde0108d6e84354e21a513fa564f5201277e060bb916a9153537fba1f7",
|
||||
"0x1d3c6a780f1b259e096f4a141ab83cb6bd035407421e2468e743daec211e536f",
|
||||
"0xb2f47534f060c70f61a7c16f920d0e11b957bb3ef912ed9292f35b8ceda2acea",
|
||||
"0x03e0ebe6e9992f6921362d463b68f91518d91079c001c6bea7b3452879fdc29c",
|
||||
"0xd9a7de173a1617ad813a554a56d7c7d2f010ac78d7782e524b35b5c676cb72dc",
|
||||
"0x90d05d99167e53d34a02c5b66ed6920190370656905465f20efe56499aa0ba6b",
|
||||
"0x17702606dc895aae35aef034fddf8f7235efcc66e5c9d252347063209c2177b0",
|
||||
"0x3c416492193d81fc03b5c1964989a314e5ee6d689c638c996f6761b4d7acd6be",
|
||||
"0x3c6c1162ea9b277f831989ea26e14bb23ce4d72bb9c865e354992559266ceb16",
|
||||
"0x96de93f849613bb2ffc117bf111d4798b9252649f94f21187da324a3fe363833",
|
||||
"0x91e50fc6e564cb9d6b7aab3a6e93f6b32944d5a781196a9a8b12ac7f6f527565",
|
||||
"0xdbefa2bb2ee620d75295d0f3103e06b428f955dba1a792421e435051c46f7933",
|
||||
"0x78f29df98ef7dce9fe7b4414da90fb4df5d99231ab0a3b7a3e70659986580fe4",
|
||||
"0x56cf56899c2388d55eb1496ccbe62041d14cf655c9dbc53984d86c22ed281acd",
|
||||
"0x099f52c675171088550a9e93e1ab17f003190fa3388d956724d422e5925c4813",
|
||||
"0x9913e4ad8405b8a60fa512fb616c544c6cdc415cb1023aad0669d58cc3810161",
|
||||
"0xbf5d51369b2510bb57f8fc8e9342890e8bb37049079dc79ab97afc0bcbf3cbf2",
|
||||
"0x3a012d45d250c818b641fb18b71b622f5bdf0b7a541e0d8de54f61e516ee3ce7",
|
||||
"0x0233833414d2cff3da0326f7baccf1bd522db5fee290ab4fc0a976934a20358e",
|
||||
"0x38a0978c955f20cdc32e2013a5373efbfc50924e45e9c4c756291a903f4162b4",
|
||||
"0x4107f33a14052662a0469ddd646ab6659006df131c4b0f6b0e6cfd331b46fea2",
|
||||
"0x8074fb5054c755c912bc68b1dc22ae40ba13c06912c8af1c12652eb4d84c6503",
|
||||
"0xf6d151b8f9c26c3a31366d967dd7338e80e8107b9b81da0a98faf16df9cbc91a",
|
||||
"0xcebb0256d0a8a4b22d2341ec7c48292c3226caf4aeaa2003ee36dde25cff833b",
|
||||
"0x5fa9ac499a2642b0cb7ca365062c02588f9c555bcdf584f533ee8e8544b9928d",
|
||||
"0x800c7f04db30247318b8d4c11d575dca66bf615674fbeb9e8c20f387d907c8e2",
|
||||
"0xb0a43de06c9d48afefd5411d759e3c6293cbea4a7c6d862b119182ea02af81b7",
|
||||
"0xb6e7ca0075d28959cf87d716fea885e9e3a0062fc7da1b6e06089c808a632b8a",
|
||||
"0x734c1b19f0b5972b5215f675cf60c68c12cf6d6bda7b5a95ee9a781482e68365",
|
||||
"0x1995b08fffb20dedbef592ac23a81d87129ceb396e065265dd4a6cb876beaf09",
|
||||
"0x051082047a6b579684b5444ce5b75bc630277ec06b0087779387b9d7fcd18fec",
|
||||
"0x4aabfe145c368e6878e2ccbdfbecf2f1db5c9078650696bb3a584c14fe17177f",
|
||||
"0x42811ab68b304ce30fe896c52b53d861abc3c8b5e4e740fa97b1695db9a6691f",
|
||||
"0xd90cdb12ad64f86b2aa7afb781c00301f50206b05f1543b111c2b971ed209c94",
|
||||
"0x385435507c2ef42b5f1760b97497e8a02a4b5ec4926c3cce8569fc0f4be59ce8",
|
||||
"0x2d7a4908350c9cf022920cc51e0cad9c3c05d1d14a92d72310b52f984c857101",
|
||||
"0xceea9c58106f4f806a256f64dc04e1c4b53e6cc5eb048f3df7a14f8de3506e96",
|
||||
"0x7032f864eb3eae8d198c3f8edd9cc2dfe88b9971cd01b33318dcba004f9b044b",
|
||||
"0x71bfeb4c183b20fba60e225524c809b0864fa14f5c0137accc36649ed0712e5c",
|
||||
"0xef0ec5a2761c46827110c20e14fc4aecadc2407541ea046de09a58cda3b2e839",
|
||||
"0x5e6debf328055c9413fc3eeca28583f917b361a5b5bda9af4306929931a4116a",
|
||||
"0x1aab81df07eab969189333e5b2930fcc1b88a525ec5bc6af6626fdcb202b8f34",
|
||||
"0xbdbf97e1558711d4872821b9400e03a811c61096bb838d3126b1c2154f8fb776",
|
||||
"0x7d8aaee482933ffaa97777af3e4bf69ce7d99afb24e546d2e365d445d3d0190d",
|
||||
"0x9da421621b14164582b2b877090c9a956f3a7c917031bf743a9ce457b6292369",
|
||||
"0x050d717f0433a72b17a0e9a1340f26aed5bf17f90c08a5b73e675860ac9c24de",
|
||||
"0x80551d3ff835aaf987b9ec056a73a3890985ef551431daa9d4aca10c81cac7fd",
|
||||
"0x625a5b5aed2660d32d2fd8c4d1bfc248365a5cddaf9b5695e3f131629739ec60",
|
||||
"0x7d86bc2dc5914d16b3d0d882a5db0230b4b688cbd8c81098d2efc5080e589646",
|
||||
"0xfe42cd832cdffe56426031ba7d837c56d86be72b89ca9f5474bd08db80cfe903",
|
||||
"0x0ca30e1fd3bf3e16a0e295ecbb442757248b2ad47baf88fc37d6c55901e709f6",
|
||||
"0x2a83ed111b99844e17fb7aa69854525958255ffea04e0bfdc365264e72b349db",
|
||||
"0x709779de19590b69864f5b9228b3a1c334724e20be006ef5ae38f8c05eb6f37e",
|
||||
"0xf09c664d0e2e88ad5418d14481fefdc9e9c46158bc5439ffe0bf6d6d5ecb2eda",
|
||||
"0xf350785dd3617ef73b0a5bf439ce5c49adca0c041b6b5047a664e5e33967ddf7",
|
||||
"0x8fcf87571154dc4eb0a73c6ee31cc0db5f4e064cf23a255a408b2f2c7cc9c0e9",
|
||||
"0x75801fc8867ce7c75b3148c6c022d7702143b93d93c1fc2349e3e969d0179cae",
|
||||
"0xf14c18bf68ae881d3fb07f631340b00557a83860d0ba0efbfe55fe199176aff6",
|
||||
"0xbe48c727fb6a32242229eaa09146c76522dcf6bed6d1c6fc1bebf86b5e4ccdb4",
|
||||
"0x8487b971e383272df82cd812a0bf3a2026b85bc3897b4ce9ce48afa00849fe00",
|
||||
"0x60d18b465172f59c0d71594b5273a90cb41db24a5d4c9fc37020f9d8c467a4a2",
|
||||
"0xab4e36d9f17c748c87d89c23b667e3f4e3265e77b62dbd9c92659026f8a53d12",
|
||||
"0x2c711e8eec1be3caef6e16a03dcca83dac3a565c93327c67f4e8ea9f2697d9e9",
|
||||
"0x21d7a9a3f22a163767075aa693d82a962e4458b074bd8f3485c4ded1e47c1172",
|
||||
"0x1509cac83867db4b888107974d5c8547dc4aa1db3b8e886291f0f9eb6bd7af58",
|
||||
"0xa555eb6001982080479c9bdd3da9e8668bf90ca9538f16f27a45ae698ec85fb7",
|
||||
"0x1d1f4019fa3ea7ec85ee0a411560738791f2d45fe5fe6242d07267183a852b96",
|
||||
"0x2a8994caa5a27eb3081cc749cda5694da7ed3fbb8a1b4c67d7e92306cbd3c6ab",
|
||||
"0x8389736ba114022ea97a6b3e755d75e74c3c370e9eb916c0f2d73a46a6f6c396",
|
||||
"0x6a2e5d08ea64195a4153fc7bf26b7a99dcc9d31d8f58faa07510a1e87fb1ade4",
|
||||
"0x78b66b38fd9b9cd3a5bc9c91c6f816153c2c28c1055f7ac9ad12ab61f9464850",
|
||||
"0xb2f77834f7a88c4354763a28080d95be44dcb380d01f09292e679a6ed274b179",
|
||||
"0x2070456b2bff0c30ae26b2435af82e153094aeea8102a75541e02a39e9ebe717",
|
||||
"0x4e3bb2fbdc71602a62f0c423aa45398af09cf3ad24f0437027b4590e7056b882",
|
||||
"0xe877208750e7569ce78215659ef78c1656e98b63ab6cc3e1381d7581afbea99f",
|
||||
"0x8c9d8132d01b83cffd1a1fd9d19a3d2fb3a58a0a28602018db44f8b6dd5fe1aa",
|
||||
"0xcece8a371b72873a660f4077f98b04d6a3cde1a150852db3a194a293e6a08b72",
|
||||
"0xe72c8c7211acf2d67bf904cb3428c6fd69c8bd679d52deb3b2e749d5a3124b86",
|
||||
"0x504f53693e747fbba7475dff1aad887ad0124d48cc7892ec488fda56e31e0de5",
|
||||
"0xddb3ce7ac0c7e2d141df857e9e5c083d66f4a62ead742bf6631756a72fb643e3",
|
||||
"0xdc1c6a45dd8308ea319671732de7578a65a025852a3cbe88aa9c5d770d662990",
|
||||
"0xb6a9df772bdb5e7cdff569bb9d3078c081ed53e870f9171a5b0369d84fe6ce50",
|
||||
"0x1b436a7d8c9af357c8175430e1d0d3057096c92bd8bd24fe285fa55673c68b72",
|
||||
"0xa57ce7fed7521e26a908ead89253bc57939459b4c34fba583eececd0f9104e2a",
|
||||
"0xb16c4f6bdce8de6657d049e2e41f91a1cef8623671eacb9ab02fff45cee7c0c3",
|
||||
"0x8d23f3ea29767da41a2090cfceb56a65236a405031b69e614c78fb79c1847651",
|
||||
"0x33149d4876fa24dea4e872ad1da120e01b14e8f9f8270611fced328a36df25ca",
|
||||
"0x266c558486a85de2536e8849d49443e7d39797a6ed817ad7217633c28166bf06",
|
||||
"0x2073a22a1f157025228f8fc82bdaff48d3cb1c9b004ac2cb867c2cbbe7cafd95",
|
||||
"0xcf643d70f96101c99cedcc2d169b0196c564e7a8b235ae093ad25b1ba8981d01",
|
||||
"0x1489101bebc1b60e4c0fa37a94bb946f1b51ba284c667e4b2f3270ef9d264d41",
|
||||
"0xd2eceef739e2601390d872bdbb58f8d67864b000f7fbab07b0354c44279379e8",
|
||||
"0xf67a02d7e7e6da127015e5137f90e30ab43c2e828e62c3f8fe68ad5a0a3011fb",
|
||||
"0x01fe94220a07efc2bde2404c584f67e9b06e47eba05e50e71ad59710d9d6a9fd",
|
||||
"0x509bc80d1a464116b4f234001c3f2d7aac7772cd6ec5fa6ef9606ab8ab273127",
|
||||
"0xea497db1233691b3b86d8fc80ebffe28e6863f445a0b352a1286412a94ad2f6f",
|
||||
"0x80074f0e2cb668b6a8e5b454db4ae5cf2482894f3ccb7648cfa26b3365a0a54b",
|
||||
"0x56c8cd15e5e1a21c6f32f7211d18e1e56c89da688cf11b80c9e55718514eab24",
|
||||
"0x6705989758f03a8c4ee93d44f53b4114a10337694197186b62ac2220188a6879",
|
||||
"0x7581fbe2b0ae6e0a61d073fd1700c3111d2e3e8d9342d50800ba05d026c9edd6",
|
||||
"0x254548091369ad8e0abbd2eb4e31e2c08c8e9dc0256fd0097e50e75831946924",
|
||||
"0xac3119a5ba40f303a9a70ecdef9b6d4722c6adb6592a0cf52e5a312a1a0819c2",
|
||||
"0xbdf30bc3cd852b882c5d410e6d4419e0f36ed17b761b58fe58ded980829d1cf8",
|
||||
"0xebaeb5965563f6fa71006d8c2d285e093a167630c319cee2dfa961c4a583b60b",
|
||||
"0x6cd6717885bd50263a97574e8a56a3ccbca88229bce595b38a454c1184ea94d5",
|
||||
"0xc9bba3a4a72f0f08663e3af36e2bac2d4c8422b2e3c3bd29705e5b86e7c42a20",
|
||||
"0xcc442230a4b6aed5a1eb2b8744a09aefe3cfb9e477816edfa829dfbd3f7c2bc7",
|
||||
"0x4ee48471e3326144c7a48b15fa5f39691ad9f24b82430ca281eb961b18019e02",
|
||||
"0x35016779dd877530f99b1d3372a0a77eff7ae831208d2bdfcd0979b838190acd",
|
||||
"0xe3e9b2a4adc4b4e167376b33b8bf2a00bd64d52f66f4e7b291ade123e8c04402",
|
||||
"0x5a7d1466e2538b62ceada9577079248788e912e23c4cbc52d7b82a1afbf28ec7",
|
||||
"0xb8529c5a2b2dbfb72e70165b9c9291e7c02b43f157092a9b59f3b4cad85fb587",
|
||||
"0x55e90fb666a950f38ae41732269cb69afca8643b75a99bce508a16e06685fc03",
|
||||
"0x651f45996ed080d8a8dcb78550089331ad67c2df33330d1871dff956463aed3e",
|
||||
"0x9c6b4a961663c59dde3a4f0fdf7b68b0b5f049719ba0d10d841855cffc7ee166",
|
||||
"0x15c4d98e0ee4fa1535f83625a20bf1a491852884f8fe608eae6b9bde45986779",
|
||||
"0xc7891cf34fcc61935a43f37bd7f23b674c785ef3b2718358fb627364f3d8b09b",
|
||||
"0x8105fb76c9e1281f0f0d7c520dc6cd1d546d1b4b29cfa398eecd7965af57f408",
|
||||
"0x2a141f1c4e1f1e7be5d10c444dde3d1b5fe1a69f23506d5ed1842957375a1208",
|
||||
"0x9d2313d34a5a6873f2ae1e2684db00e3b693ba962796fe7e78d26a2c49104471",
|
||||
"0x84d0245b1537ec1fae89fd39741d3b6427ceda3933f750befe4e2d8ec022fc1b",
|
||||
"0x93d281ff6bfefc7f94058a0d87cb826b97728c9593ef4876b88c35d26b2163bf",
|
||||
"0x9018a352b09cb36311d0b54bd83a33dcd5dca5ae7032f1d399fec3a0e5a9cb7a",
|
||||
"0xf01486ea17dca0bb45c245c9ba76d20d1a2f4eb718b7d07fb5183736e5cd08c5",
|
||||
"0xf797fec0a8cddb31ace66223e1355211e41211c4bfd33a416c8a1a86e497f630",
|
||||
"0xf24aef69daf4e2b90b4f3bdedddbabbae86a7fd1182947da7306c8145f82cc88",
|
||||
"0xdd14e34cd000ddb6ae6426dcd78cabbf6bfbe5b3ecd7553c4989b3891e506257",
|
||||
"0xc01ece645c7430801ee26b20ad215e221f7de0e060fe004b450b372a6c4438a9",
|
||||
"0x64c836653383bcb165207b80ee8f9377ad25ef1bcd6cf7ba166cca78419898ed",
|
||||
"0x6b1cdfa195df272d7e35ccd843191d5725919c0d8b71f1abf4b950a954770503",
|
||||
"0xebe51f94a9f445d83180c4f075d944fa2f05b5b784b7e3cb4bc1544020bd35cf",
|
||||
"0x7007f6b2c04420d390fbdb6a9fc21edd3249c1a098f8a9383131b8be50c6f975",
|
||||
"0x6b7e93d96f74fc2b068104a017fa5fa74836e8be5599865309361ad9305d9bb9",
|
||||
"0xcccf2dc238c68464f3b0446e06fc48fedf202e366ace5734cdac5a7fe7c43342",
|
||||
"0xfec77750c277cd6bb0937d25d7f598d07cbffb1117b6232e932a296f32b45ce5",
|
||||
"0xb04e6883c11ba3f2b7f0301936c3dcb622f6f78b3d3d57e48c6dcba063038d6e",
|
||||
"0x23fe83ea2f197cb97a3ce5f2afd75652cae993f30bc627e8b9572a0069ae088b",
|
||||
"0x44cc6bf2cee513c826ecc0c130a32b61b0153129721ad2a70d4503b71c128247",
|
||||
"0xb1a11be5f9b37faf1901b1405494af32084641dc02685ec33be7f6e82e360a42",
|
||||
"0x284bdf9a6aa0ac964b0f5e72d0d47c713c919d72fa9e24f42b65d749efb6e2c3",
|
||||
"0x96a0a0e92ed87946a322c9bca6c0ebf70e51e0e825e2ede85b975349f9bb2caa",
|
||||
"0xd73becb6a3d9a155d46a96d17412cf015724a79b166d2961d24125d92e355947",
|
||||
"0xd87f142746611ce081945999f42b8da49cbda03a10bf953ba043417861e27c77",
|
||||
"0x4af010485b5385579a534693bd21ef3768c8920c5b5dc6f9ddf722cc68fd6550",
|
||||
"0x65a2f4ec5cf3b37530fe0672418214618393db47ad1185f285b445cf5f53cf26",
|
||||
"0x1d208df2a2785599565a40d934eb2c0cc1673c1dd43d11685d698122ecf24d6f",
|
||||
"0x046b7211427f0027ed4b69b06cb43986d3cd53d1579a2e078f6904a06ee6587d",
|
||||
"0x053fb3ccc35edc1a1623f8652dd8c239045b02b58ffe7d51337950ae43365990",
|
||||
"0x0721f82b52ff87272e1b0af5f4dc16b90dfaaaf3ba56b91bef555d283c98a8ae",
|
||||
"0x26e93e4e2d0df49a857bfcede7e6ac234d75b71617b561ce39c3db130449e4fb",
|
||||
"0x5ed6d53c35a0aa52d9dd0a244f31be00426292c11676737c7283f567ba485dbc",
|
||||
"0x047add17bd1601a06a32b721165ecb2afb55290e025a828696f234b95c52eae3",
|
||||
"0x6f9e6884745cad7091646f7767a6b17ebffb6482ee4726f5c1f3b9e02d26b77f",
|
||||
"0xab29ed5be2938fb19614da621ea9828eb338514309b3d56efc6f19b57b8f4f6a",
|
||||
"0xd5f14043479e8e37c6545527b2e93a76763a654661af9a25adae2b37dac40672",
|
||||
"0xc43635c1489c3cf3aa231419bfcf7bcb2455a812e4781e5947bb76cf0219d1e4",
|
||||
"0x72117c92f8bab83ccc7fbe5fc6cd931c765238ebd67ad8c4fcf1353eb78c8df2",
|
||||
"0x5deed7df3559ed75d7c2388a6e583067222684741143350f85d236bc5fb4075f",
|
||||
"0x655bbc0590587c030902e32d88cc9113fcbdd5c3371820868768abaeacecb79c",
|
||||
"0x1641c875e8e44b1fa71badcbb4f724a71e2f916d9cd212f09e9039ef41b1242f",
|
||||
"0x40bacdc3f0b53522cdf2aefafa2bbd9c8e9f8fd25b4b33bc19a87d72a5de293d",
|
||||
"0xc35c6cffaf93170662a6f3d4a0152c988b0f4916a33d037801f6f589a6140d08",
|
||||
"0xd4e37125c0ca7844e048bac4e4c6069ec24b0493e4547f53679fc8df2a1e0d66",
|
||||
"0x34c6bcf0e01dd55a1d3a82df0a2edcb2caccbc4be93fdfde32c7718276e59bbd",
|
||||
"0x78e50d394d9d42ca8aae3f4dfccfb32fc3923073a6643c010fd49ec3897c4fe5",
|
||||
"0xeba75c237fb213e893083c5ed0e28dde3ec1f5f1b60edfdddc17a54de9cdfaf3",
|
||||
"0x4f35b9a67fc66492fea331378c479eba921fe0a6f0589b5ac07a44b1ea9b4995",
|
||||
"0xbb4d09d98b27d672259b608f5075575cca49f87cce0519813c1ba4a614d369ee",
|
||||
"0x805550ff80be2d3a543d5076961442f70dcd86e82762149c125d2ce371a32f69",
|
||||
"0x7d81d766cc2d6c66c7bf07be0a416f2a4c0dd2bd94026270a410ea6a051dd4aa",
|
||||
"0x30edcef101041c0e0acecb8d6c15a28c70b8894e56196cddefb5fb6b39658ceb",
|
||||
"0xe5e8d21a00ccabb5cb50b4d04ee1dcc217fb9908e72bf0efab69d4ce7a0b7eab",
|
||||
"0x3793f78e2e582b56fb3d24e3bd4aa69db4741e768795f9681285b0fd34ebd602",
|
||||
"0x4a9378b4ad76df084739b2a63459ac67abf8eff7499210936fb9e6644265054a",
|
||||
"0x2e47b62375a267e104ad2f8bfaf5c985fa7c6f4c438739810517e41141a825bd",
|
||||
"0x73dd638affe08c104b37d53e6cb7884b8a9b4cd4afa4bbec6ef608bab4559dd9",
|
||||
"0xc566dce73da1cc0d069a032045c44ac4ac86b145efd2cb1c363a2d403fd8d7cd",
|
||||
"0xa1a04d193c5408d0edf85e771c6976c5dc8de08c87d906b6c9de1efa4b4fcbca",
|
||||
"0x3245d987f205b01c54448d9a9d76bc7e4174c1021726a68f5feb6748ac373f8d",
|
||||
"0x1f963274b936dde92281f2acd47d3685261b03845efc7d10ab8b02500c239af0",
|
||||
"0xa1e6d69b28aea5d24c3dc301dfb0d6df8ee8fe693d1d0f419cde3b4d20d22a89",
|
||||
"0x31b0711795c77cae9e1b62b87244a5eafa4b1764aa1620d53be7e779db060984",
|
||||
"0xea141234dd00c54ec7912c80baca591b53a058b81fed1673317fa4ec37c2c715",
|
||||
"0xc5902f3941d647da304e94062951b09f4d6da5bcff71517c7a35e8b49c6ac569",
|
||||
"0x54c5677af7e31b84010f8b2941ffed5080e9b4d18b608fcbd230f163a5e04ba5",
|
||||
"0x1a12c56542a01bc58288a58e8e526f2b2c81a5238c83bbfe4808d206b3b9d0e4",
|
||||
"0xa398984bab81b7640674893496b2346eaa8257aad4cc8bb52474f7162fb6fa2d",
|
||||
"0xf454a592314f1b7459d21eeb6ffe54c96ae2e25a7051dab1f8129518d3788cd2",
|
||||
"0x12964f85bcc410fb40e89f518d749c7dc2be7546a960849dcf560eea2ec3d333",
|
||||
"0xb176775c2ff94aedef2c099b936468986874d17eb563086215525acbee2fdbd1",
|
||||
"0x250de6e94d60125bb680e862fcb70823d06e4f27308ea1ecea8a465d5febc860",
|
||||
"0x731cc6817fec665290d7637c67fdbc72bbebae70a13f9346f47f3b368eb1e4a5",
|
||||
"0x489e955cc77f16d8aa16bada320127380315eac978f0fd1033baa04911123332",
|
||||
"0xa88623d9f89221dce46b55ca7248581b4e3ace94a7cccc9fd44a3b03412fa729",
|
||||
"0x4a65c1808d79577b36dfb5fa74d0deb96e90d0105ee373d552685cc4f73d35d8",
|
||||
"0x7aa8228e6f8fb98a23e1599e12ecd84c879475a23f10660e763e338a347c9002",
|
||||
"0xa825d02023ab76478b83a2a61dcc5cf6c05ca741b960043adba3f13d1c99612a",
|
||||
"0xd3c90e414048510d9594ae7a593e25641b6baf93f9625cc4a3caade094f02e07",
|
||||
"0x4d631d9024a4e75111189835b4ec0007a6951d710512dd7b91a8d56da95e57b2",
|
||||
"0x0158c7f49affa675f04aa4ebdf11e88bab8c6dc0abfecc0100d32489b0d59f1a",
|
||||
"0x4ec96496694ef53e17b11b3122cc45cce3a4fe1a252fe9c0d379b302db1318ac",
|
||||
"0xeec44b94d9f6c7359047d257ffd5f1f5cee87b3ebd6845dc1fe48be686a9ba69",
|
||||
"0xe24c7b667382186196e5da605ce75a5cd9c7e4803fb2e268b4de5848737db026",
|
||||
"0x14a551850f945f02fa2ab84c6ffe3d17930c81f5b15e94ce92342c3646b8cd9a",
|
||||
"0x7e9a72469a52662bbcacd449dc7df8fa75e5cd1480dac3b635148a34e0f9e375",
|
||||
"0x2dd4fd0394574c5d8c9272c42175e3a88d8501753bb25a77fa937123d0c2538d",
|
||||
"0x6f044eb54fd2b8e51d89f6db2ee6e654b144d9e69cddf79b7899e06af5bf39f5",
|
||||
"0x091d894513fca5d2239f6b5ce73737aa2657c90c2af196b2b893ba0b0205859c",
|
||||
"0x78b9ca580e3eca0808e60420ead000365eeafa60c6394e055a653a7f536c8b6d",
|
||||
"0x595cfe325aa600ef0d7de6b2eb717b33c92dfbb1e3ecb9487fe332c878e9f121",
|
||||
"0xe1dcc22aa44a0243f67dcb0aef7e0eb1ceee269b0faa67633698f8ee29155115",
|
||||
"0xddd3354d4167161c6b18173ae24fffac2cff12a8bcb3ddf1d964907716685cb3",
|
||||
"0x55c02c02eb758f8c9aab60a2432d29e73b567e3e3d0148611ce4569fa074c5d9",
|
||||
"0x5d07d5a7d45fe16a0521c55b3dd898b922c619e5b938535e2f974f11b4edfdc7",
|
||||
"0xf75100a1a2f8d6daf0dc36569cbf579ed6e52838b163fe50b5deaad8fe7bd07d",
|
||||
"0xb6391d028fbc88825eabf1dc4566e58112e6d3b7cfe6d387d0fa58df387df78f",
|
||||
"0x8a58fab34ada4d30eecbad64a001015c91e446cf14e95c9d7a3d894530787b03",
|
||||
"0xac13b36d0eb0483ab8cf21f49c78f9e32092c74c878ff520ed3a3c0080fdf5fd",
|
||||
"0x358c1021fbdf028ec82b811cdeb504adc2611a1ab477e8a191f780592d598361",
|
||||
"0x6a7af25eb6d089ad63712187d1414e8bd04fb6bfbac26e6086b1a3e2d66f6f7e",
|
||||
"0x6bebf617fe66129dc8c9dadef1a74df05567ed2fc89f4e5c4dd36327d6b0a5e5",
|
||||
"0xc658d76eb9f3fb91327c64668b08d3e9bfbbb2099bf5d9aeb6a61b8e4f893c39",
|
||||
"0xfe68ecc66eaa625842068f8b5ad4bdf5cbce0c82ecfafa4bf48b08de49c58595",
|
||||
"0x26eba0a168f2e5f3ffcb37955839d37432b39f2f447497854d42d802826fb1ee",
|
||||
"0x8b4f8964062d0f00e40a41d21852a2e22abba1f4cf75f594797e368e4df21f7d",
|
||||
"0x916993123d91b181d145e2668efed6eae3845fd76d4765df3a04d8adde8c7142",
|
||||
"0x21b91051b5c5fbd22164a655de8485cfc2a9eff58ed09d6fbbb454560898daed",
|
||||
"0xb52ca76065bcf43f06335977ab87d6c809dcf4e6cdfc452ac2018b77c64089a5",
|
||||
"0x9437d47e7f7fb4c95aacd5e1322a9c7b457888dbfb1e485142cb16ba805b5ded",
|
||||
"0xb7cb3f7394fef7de5884e165c8441d441c98c1080865b604dd21766759f7fffa",
|
||||
"0xfaff33c1aae8882f3a9d84678b55b8945b037b1f05785f2874079da71caf4aa5",
|
||||
"0xe032d77db9e882bfb3d5adc89d9a9812fb9775f98c03765ffdf0c40d0dbf11f8",
|
||||
"0xc9c4ded5821040df911b23d92d8270fc83164531c9d631c4d8e228a71e189ba1",
|
||||
"0xa27f4dd47059fdd4afe78ce8c9029c9a7c0916d10cc7dba1ce011c886d2275bb",
|
||||
"0x6dd0d3b0e07535d8350cb888c75ca355c4abb07bfc6ceba3eae02095324679a0",
|
||||
"0xee4a3c6125a5e69848457d35f9614705b651c68857b03968bc5420a809d1d9b8",
|
||||
"0xc14947239d0a7061d796313aca233659059b13740e63f967f8bd4806feb895ff",
|
||||
"0x36d9ad9d6ad2e1a1aca489524303aaa8534b137c5e9ef708d589b7a75cbf6500",
|
||||
"0x497c4cf7509b12ebd34d5c0520a24ae1b6e1c5c050bb3412d7d1a702c48d07d3",
|
||||
"0xac81f9bcce95283b7f188f16eb68d22adb22dc1cff0853739c46f27523a653b7",
|
||||
"0x2f0818ee594d2d1fbfe9a6a03cf4ae08dee69fbb9c289c2789d792f14a3e4e7d",
|
||||
"0x9beb888d86489512a9d1d8d6461490e23599c1595aa5b4d4b113d18c0eb99697",
|
||||
"0x7708aa2a88f9b41cde9f338da6d2f9dde2b57f1538f7aeefb66a0e9dce488ff3",
|
||||
"0x548a59ae0782fc5202431a472a8dc5e21ac83b68dc88afb2b0afd56cd3e880dc",
|
||||
"0x271397f861034f73fe228e3921d835a313041c260a6c2ca3d0c28d407d17ba89",
|
||||
"0x732b95d3ebdf035182863a540bc002cef70f98b91f90ee8dcef2285a970ade6b",
|
||||
"0x605d419ecbcdaa05d6f09c9734469847f52164df26417d7807f959986b843869",
|
||||
"0xdc56e2800a637475662632ac37e9eec90d9f3962a454d6f32ee7f56426ab9f42",
|
||||
"0xdcd35988aa6982f14b3a2834f841c755ad42dcc61eb0dc6122f2aa9db65fcf92",
|
||||
"0x659b06e2aa0359e3743f59d2b128cf85bfabc20ac9d8c42a89d9cdda2bef7697",
|
||||
"0x45377222c3910f95b3f5d0adef823dc4184189cab9eed54b9997d2b30fdbae43",
|
||||
"0x15d66d0b9347f12bf9c408910edf41623f460244f309076d55cf969dc158b36e",
|
||||
"0xe5de2158113351c0ea314eb12b28f9502c307decf883ed480c53c1310c9f7c11",
|
||||
"0xc7342c08dd73fbe5801cc6c8764c53f924d6a77cd5a5b8bdbb22d2b6d3e0336e",
|
||||
"0xf10486dc44a10f7eec6739dd56e0f7519507777e78e3974d974ee0bd931f03d0",
|
||||
"0x5985752f0b3849e9cc6a5d38b65617be10b52b8fd0c2642c328b864d59a23f9f",
|
||||
"0xce899213bc8a178cbf2a8eb86f045f59895530b0af5e209b60553869000070f4",
|
||||
"0x724dd7b5e5d0e93017a62faffd534e423610c494ef0b5689304bc80a68df0e46",
|
||||
"0x318073daf925850c412d6a1f2db2d2093268896a88c49e822ccae4070b406408",
|
||||
"0x74fd03921ea801d4618fa7c2375c4369a15c7774564dfb0373b5913bdc9a6df8",
|
||||
"0xb10896436461c2660cfe36a60c433b32ef8a1e772f3f9c16ae243840a1aa3aa8",
|
||||
"0xecfc10478a368b186e4299447ec9d3ce27ca8386274c545f3edac3608ad6cd0d",
|
||||
"0x288c697b29a0d2c5d45b9507aaf62bc4bfecca1b34e1a5ce13a17711af0df3cd",
|
||||
"0x429fc79b89ad00887096417282a571de77fe73dbfd1564c13bec5830b38890cd",
|
||||
"0x4d859982815d597e31d0e5374d7077b59a4b9beec01040608bad05c6a9d0be2a",
|
||||
"0x1addc6e300b6120cd196bcb7340ca163879ac55f7c9069be77947aa01e778cf9",
|
||||
"0x2e648a4eefda9d35e26b148028a0b336ef7d75809454e36795edb9d3fdeff550",
|
||||
"0x814e65df8c720e8c9c7d64c76b6b9554328d6c780b5f3dff96aa3e29506e7e49",
|
||||
"0x4841c38f2a920bb1a072b9a7853dd7d2e44dcbc35e2737aa2f3cf6652dabfdd2",
|
||||
"0xdc63afe7974211db82b2602c26d6ace8d93f34736c0fa68eac3bd5d2c1af7484",
|
||||
"0x2052d12d3534c5d7693d420c8e080bcee99ce10ccebc7451272b7ef08f8a3dc2",
|
||||
"0x4985769df508ccc2add583d187095a8af4ca73a5be2506a506146e23dbc67d55",
|
||||
"0x4a6744d48fc2d85cc99e419483ec1111ccb6fc7ab13e4eba28a29269acb30952",
|
||||
"0x527b0514dd83336c0524add1f01799512517378b2045c4ed43ccc0e977553bac",
|
||||
"0xfc33e6a20033fff41a9b885dc5bbaa848a0f244fe89b4a1af261d382c544fbaa",
|
||||
"0xadce691a1b4224bd56682784ec106dc93af89185721db8b427eab6b0ff22776c",
|
||||
"0x0fdef2a9525541c1e96172c8a33ccc08ed759dc024d437b82126ff03b65e1684",
|
||||
"0x7aa9e8c1e9da3c68080f099281b367de26838ec7bcd474590ae101fcd68a7116",
|
||||
"0x7eb70f0a4c42726f5b3a67ab12bdf5b4e6bf5e4c347b6c32f6fd3a04c4a003e5",
|
||||
"0x546f5f3c2e44b7a61d6d0dafd802fcc114db7acb7f887f0dd0b1878979fd3eac",
|
||||
"0x5c5294fd77081b1a23037c34170b568358011be2fdc0e3ffa2230b1a017ec5b9",
|
||||
"0x6c854d3de1f2a28dd8f6320a534b915b032078377e3b880eaa8e9a3775768e2c",
|
||||
"0xc2be1a4c7a5351063084c5907f19e63f25e048f3e27648a6d9056d3d4b635c19",
|
||||
"0x5d0673ecaecd00cc8847827bbda1dd7bb21f537e5e10f10d8b5944496b55e9e6",
|
||||
"0x8a1bfbf9dd51b727c17e8920019caae599f53d37563935c584c84cbdebf942e2",
|
||||
"0x75649056bcd2a520811d8f9d5c0c629f492e93fcdcd298c0657a8c857fdf2cc6",
|
||||
"0x71421a3eb42eeba485fb90918511b0a430311856c27a968e52096c6cdaf0cce1",
|
||||
"0xdf19c2d595ec81bacaabd39217e100e6731f8bd7c3d6c5bfd987b27f89be146d",
|
||||
"0x573839677ae138670609c499107217fcae5de5fa9905c78a21b07f7a906a0a53",
|
||||
"0x1e8db73865049c1cde4004c2a60945edd9ce9847c360a2feb36205e1f1cbd5da",
|
||||
"0x52a602e7c2f462a39288465c733d2133b7f77a7a77d7e60e214d4d4eff917258",
|
||||
"0xdc30b1767c78f2ac953c5046e6440b7de488933cdece18fa3566f00d8a96c92f",
|
||||
"0xfc0baf76004e7d87b36ea52de7d886c9b3be44bb8063549bba31b63b87ac3f92",
|
||||
"0x3426c56db720ccd184f2e49385e96e5a37fd378cd486de8fadcc7d5e727aebb8",
|
||||
"0x39fc1cbf20cab093c75b42931fc6371e9851cc4357badb6961359e07b9d97fca",
|
||||
"0x6b3725ada81d881bbe245d4b55c7be12926b42d0e58dfc8fa38d54f68ff79ee4",
|
||||
"0x69bbab0d123bbf03499984698c162f9dfb81375f6bf9f2e643badcc8e0281ef8",
|
||||
"0x101cf365b31d4b37910433ffa265e1a978d4f80c478936809e1bcca7baff59b1",
|
||||
"0x65d26a27a34ca4ca98c2b5f609e4596344514698f2137547e815dfcf91f5bb36",
|
||||
"0x3b8598589a6ef43efe0b7a64832360ab02e150c4b4ec02f2a028d2522f4c0ba7",
|
||||
"0xd8776563bb522b42a25cb2714f9ea294fffa4c4fb5ad040a9458e10637861f34",
|
||||
"0xb1b85b8c9bea99a2bde16ab99b2d7e42571ba15dfeaf28a2897322bb444171b1",
|
||||
"0x803cc4e5c23bd3842736b36a425364416dc69a3efb95f3c7fdbf7782d6de7edc",
|
||||
"0xf5803ed2a130a19600ca887ad06813482b678ac0eee049cbb2e56e39a90d9867",
|
||||
"0xd3f6125b061023531cbd3d625c9382631e2fecc75945dd6f78f883353ec98962",
|
||||
"0x7b1d59f8c9869a9c73a09385c82762b86fcc995e75db00bda388e1423be19df4",
|
||||
"0x2b7a8289bf9f93c589866af1a224c34943433b6a5a571df7dc4524bcf2adde42",
|
||||
"0x9199d73dd306fc9038b36212c3ed7706d8b0f30cfcf3359408a8e6fd8ebab0a7",
|
||||
"0x0cc8446d21ccc31bee04addd48b50f394390ef3340745555f9d7ccc3c13eefbe",
|
||||
"0x80052b2097d7f836090ba9f94ad7c33066453d8ee62a2e215a82003ed92568f1",
|
||||
"0x231c2d4e6a6039342ac03f766fac9f0a587ef6828d071e63a1e3f660fff13263",
|
||||
"0xcfa0cae426e4b6b9422d72a687d50139654fc3351993b5d38ea4fc6f8944e662",
|
||||
"0x9dc837a60a2c18493fd3b40083996f18a44f37a7a762ca649bc5d8c8b272aaca",
|
||||
"0x30b4651c3496efed5997116b7a12f9cdc24040a4e110478f1a2330fbba48fbec",
|
||||
"0x99567d98d73fe92c81c69aa465bd62b02492839519f0380686349da64caaf758",
|
||||
"0x9618fd333f89357a22bb3101cc386003c2745f8a24b5affd2be9cc3c26a93e34",
|
||||
"0xe539d1a4de2a57dd65cea42302fac83aed570f2fd7a318c6d226dea58d5f94c1",
|
||||
"0xe69e3ef5d9d8cf08d3a354da7179d5bab9c68b4b6ea6a7e5a58cae9d901b5f35",
|
||||
"0x97cd995441161fe4f50a339c6323020db6f56b9221b549194a93b9895a043e59",
|
||||
"0x803e04ee8a22299e779491a6749b7d57973a59fe714d080f03749bccde30d5c6",
|
||||
"0xace95a4dc00b3fef757aa76445b1edc582246eeebb7c2bdc71fa648e06428485",
|
||||
"0x1c8bd27b857dd8dd5a671fb4aa6cec3c41ca1c747c9f86edca8f389ac637e09f",
|
||||
"0x554b4d1bbe92718dd1aba2a9d10f48f803287d2c26108bf3cab2574a91375511",
|
||||
"0xd5856bc0794ddc23049639fc438c360d66e4b3eb1f96516ba0c02c46cda8fb49",
|
||||
"0x25a4c78e490c1d5fc6c1252b2ba13ca9ad5113a5c64e02220969146c5bbe9730",
|
||||
"0xa8dd024efc7f03b61ff9926421107b54c42f5f9c936d956e9b6c6eb36f9b242b",
|
||||
"0x26d488bff06eff3fe1912ce985ced65325e09e1c01a95bc16d0df22481690640",
|
||||
"0x01b89e65f1a82ea7e456e96e2ddf29be42dced7c7ea9b12e841bd973506dcc25",
|
||||
"0xf0f5d3392e3fb73697e44755d38c84bd99394ec2ef9dec841049baf8166e6d55",
|
||||
"0x91c4f65d698130b132d0a33e44c27ea55f477cfb134224139ba0264b5737ed42",
|
||||
"0x1d2295b21e1bb810d35471fe17adc80e59c6c57b5037de90c88e99021ac78b24",
|
||||
"0x667cc89337d382967727f0740819a2f6298dd5f2b7b5e82dc45e3f1c15c5e998",
|
||||
"0x908ac480019af2d3c3017c413077a73905e27ec01721aa499c24fa7e13bf8ad9",
|
||||
"0xbeb7ebf8ffae71221e5ff149e3333fdefe6b11780d439b45a874129b2c25d71d",
|
||||
"0x235c2ed0e3fd286df5cabca5f0f61bfe356ad0d7c8bb9c642814d01f2fd26699",
|
||||
"0x22fc5189fb1945ae98d89e50b258514baaf525e8137e9581c99339e1097e33c1",
|
||||
"0x148256253b74711fc61f8af7d4efcf8694752426715a0a4c788556feb68c1a2d",
|
||||
"0x26ad59543cfd91bbe37cd8fd1995b81d0f095ac4e02cda0b4f5f40c9db6d320f",
|
||||
"0xee340b0f25450c23a5c9b16cd5aa59657a9992c1c341172bcc8c9038eb6789fe",
|
||||
"0x5da22a0b434f041d76be1d53ef63ae24031861dce1ff4baa3511d67664060bbd",
|
||||
"0x6009815cd4da0162884d0be4cfe6936f1b251f50e9c89d9fdc2f0af430012e11",
|
||||
"0x9342474f10ce871dfeb70fde89b181075b18e973d4806364d52f83f6be4d69f1",
|
||||
"0x3c4c598faaf3c9fa8b9c1bf856872e65e3d53435177992b29a7674198e7df000",
|
||||
"0xdf0d952cca28797dbb503cb8c7192e811a7dfc0797379391f839341e210078ee",
|
||||
"0xdd48052c8e9a9ec62a58a580abe1c420b89393bfffe53fbe6b7f9079b5ec4d3c",
|
||||
"0x028846c41592546d1d11375d00c1d10a18c06ee5f968b2ce8e8c42bee7aa263d",
|
||||
"0x4aa08dc77484d15f8423a1fb2df0fb0c67729de1d48e61831884e49d7697674d",
|
||||
"0x084c72f0f0fb1cdd4ff80ebc9379c9d29c8d1e35cc45901a67b231ac201ff9b4",
|
||||
"0xe904eec627d475fcb3e61b2db0366a24ebcc286ccda2b1614049fa17ae9a9d85",
|
||||
"0xc3fb5ed46f30f566b1d5547d5e00c4c999960dcbd1b60f0b337bff8da30c054d",
|
||||
"0x1503b399ce9dd9f1cd8005036006e4bae2b3f05fbb1393b8f5d868332605c98b",
|
||||
"0x70de442d35565513b92d8cdb95c6537f72d7e099e217af7c260fdf92499ecfae",
|
||||
"0xc6b86174c627fdb002d187feada8c72b9bc6b1fa5d11785988c72b06480ef1c8",
|
||||
"0x06212692407b9b701ed1b115a8ae1cf07668cd7498cbd7c5c58e9b52a0a0093e",
|
||||
"0xfdc722f761f07d5c52d36c147ab8e80a666af5aa77fdefa37e86c7b2518aca12",
|
||||
"0x7396bd40c5677c5f4388d956ec437071cd4352cac44b7b97eecebb6c5c99b507",
|
||||
"0xf634b80145415b2086d4a20746bef5c7d34034ac6601487792889be39bac54c8",
|
||||
"0xfb8cbee41b441d5424cbd12b064b04f5618f0b360b1c2ae5ffb90a0194e61106",
|
||||
"0xf77c56810755fe69822c1250295092fb8e7c88d789706d6769d0cbdeb386137b",
|
||||
"0x9e0f084e1184804e850784a4e376b8acbf58f4235a3829d49217c888e4e5d535",
|
||||
"0x6b39d6de64090febb49dc6f6a31eb606d8e278b7ff4fa9e1a9774d3d9dc71f81",
|
||||
"0xb5d9e67fd6cdd93c74536e5a74dac8eb8ea6914c2315c22e079d61eaecb18c29",
|
||||
"0xac3dbb4fa1da752bff5884154e02ab975e993201e69ef9ca532c8b1e00b1628b",
|
||||
"0x747b42a7005c41ae222f8c2ecd4bf7000c274366237e68b2e95a64cef3799ef2",
|
||||
"0x8f06b121d921274a0d8da269d19ffd6a417cec988f0018647966960ac822fd60",
|
||||
"0x13451d3ecba978d3c0d88c2dd4068cf060e949889ea514306c23a7a1ec574ca2",
|
||||
"0x737f8bd85cce3a392da15c8e68c3ea9748a6523ab92dba8d1c6c8081311c3ef7",
|
||||
"0x83cca9d97f8c4b2776b96d887c5ab1e8e6172970d6d237da98dd5c6ce07db7f3",
|
||||
"0xb5bb3dd88ecfe2e4ac4e4be2b605cc7c5e79024782628a95df33c4967dc8251a",
|
||||
"0x640c6050e63c965742cdfc6d3217eca459a24b3acf3a5ec64eed9bd7bbcefaad",
|
||||
"0xe74478890f186d41b5157dbcef1f2754a35a5af332095dd25d34caf01580062c",
|
||||
"0xfaabbc9703e049e49d1d22da051cfe6cae0697e7e728e954bd5abc40d0e2014c",
|
||||
"0x8aa4a19c4ec50a68a6541ecc11d4473cf02773a0ba7bb4012ccd76ae11ce8bf9",
|
||||
"0x01abdedb1886ec8220a4f6ce6a43863ab77215f03e8116b03f3efe44bee658b7",
|
||||
"0x18e44060426a05d3d9500b7d6ae6d99133109bac39942ab825ae81c551c0ef39",
|
||||
"0x19a60001bc92289e73d3a8320f7601eae1bcf70f65c3a43ff6af1b2c2c17355f",
|
||||
"0x2dbc82c8ba30fe69aa00c7abf129cd1a65e8fb9398b2ebca0843e526e001ce1b",
|
||||
"0xec773bb4cf7d35feb70ea19cb53cd64af2cd34c1e4f1e282bd3cd0b39720bd2e",
|
||||
"0xc966e10e5568661e0930bbff1561e2de413f9f89d984b46224ced75d57213401",
|
||||
"0x29658e4a7e4dec3e9a449902af34ab93fe760c6a1695c1a97e0a093e3d187782",
|
||||
"0x98b0b147d3f6a8a21dd9e3fe01082dc9031c193dec4def76e53ad1c13269c3d7",
|
||||
"0x288b646ad44d5f4ea299917a9b69c9c07b5ddc50e93d03fc1c1ed653599d7a7d",
|
||||
"0x87c26362fb801ef77354375eadedc1489a4fc39401521cb06b604fd9288e4d82",
|
||||
"0xa5cf4098a62d2dcc87e589c8269dc712e2ac2be5adf07ca33c520556d4da0cc1",
|
||||
"0x4f253c49f87e135e4a0941409fe70ec6b29f6b0d9aed3f654f5eee7f4eb0a486",
|
||||
"0x5370ae8dfa2a982dab86dfb45950a50ffd29039781b2b065ef5057f7b43b84d2",
|
||||
"0x044f950f82d97f0fa164ec4174c238203d15f4cf32dd739931c3e291e0902ed4",
|
||||
"0x792c3af8c8808b95f38d6e21979450e3ebeae129f0a9a9d0cf2951252801dd7d",
|
||||
"0x141e09e2ca0a96d50e7c12aae794ed0f22c0441fcc51d1c4e179f891cb06ee1e",
|
||||
"0xc475b7c5293efed9c9f0a5e1d8800e4dd10810bc7dd33c406da131b15524ee48",
|
||||
"0x0018d2c2e814bff6fa8f5e162de402db71dd9eea45d320f60e280a00aadafc2a",
|
||||
"0xc68336fc8904777bf8ec4d5a61f79f2e847c028889bce39ae0f307d11efad818",
|
||||
"0xd6439bee30ae288496a022e04f5c21b9b047edbb370ea3e33ed236a217c6ca0c",
|
||||
"0x03e096d6ce43823e4543ddbfd8f55528d49c38b5c701c520e95a51547b5b193b",
|
||||
"0xfb80f18124198c12b6359ea7805f110f9f25a6686e7a917c110ad511554e634b",
|
||||
"0xcf9a0aa896f5c54982a827e07314a81b58beb3de97fdf112ee1539ee47158f59",
|
||||
"0x948cb5dcc88a5502d82a292e7337d5d010055ae4964c09b2c6d55b0401e1781b",
|
||||
"0xb91614b49ef967aef3b113983cea703a60097e0cd4c0d9cf1ad6f36d594750a9",
|
||||
"0xe29abd32597fbfcffb8d185931986a8519fcabca73abfc5be6e42bc8b6439374",
|
||||
"0x9ebbe1b1037327c4f2f3c9b6191b6f28aaf9b04dc58f3314ec2c16ac1eaba9b7",
|
||||
"0x098529aee4331ef9ee00ee624912ed1a7cd8d63ebf27a96059f56e60ab9a95b2",
|
||||
"0xcab9578772277f3e1f7a6920b96df6ce3e6d7f60c42925b7bb1ac1d71d733718",
|
||||
"0x43cb7ebd27e7207228ecee10cfb11aefe077bf03053877b53c42a41e4f39f607",
|
||||
"0x12ef0a09e0f5dc9d89b01cfd66b34182e80821f0f9d86c80327086a9960ab9f8",
|
||||
"0x30bafa474c54d2912897a13911cd1df20988be102333bcb9fc54905789f87718",
|
||||
"0x383205a3e0b07e359127b28c3ad1b451564091893edc87d3d92e081111dd20e7",
|
||||
"0x74382d6b160ac8b1e7b86abf22cb943b43afc4480be4b09c87c8b796f22eafe9",
|
||||
"0xe84cbe2ed5a30d7b25ec540b1934577387626fb894e4248c719d417ff1b0f171",
|
||||
"0x068dd7e31af946d3427dd6822c22577886c32a7f1e3a3bc61ee061be7c456751",
|
||||
"0xff5309cf09f24f3666205ae09e542634bb848c47031ebc10079d96819095b60a",
|
||||
"0x82991fe8d442572aafde5e2f6d2c0ba0823ae72110c2f4b65a0d39244db460a0",
|
||||
"0xb86d9c8e378420595feae0f728e00736f5b72ffe37e289088c03235b3ae8f556",
|
||||
"0xd678cbfb25960efc5a64d48f2ada784a5b43123da5db8636804c2ab7d1a6cc36",
|
||||
"0x1ceacf6ae9acb6e7438e6971b133aa7a8ba7b648c130962c3f60b7449266f3ff",
|
||||
"0xe81d2bbf5efd047428040f86caa351a8785a0ee864e74760569318c997b25116",
|
||||
"0xde530285d36c4a50d0f91d48a42e9b85de919e51246b6aa54a55eb2041b17289",
|
||||
"0xd5b86ba5c24729d199007133a8000314476135cc5b84dbc49de41a7d9f3060c7",
|
||||
"0x95b2fc8a95f67d4d67cba712a98bb3b35fc4b92581f5eab9e737f2555592bf3d",
|
||||
"0x9808b933e2c732a2b4d6229467430cd73715ac93d1000c470dbe403d0f14b6ce",
|
||||
"0x8a708bd8ec41b6aeb1f822ed4892c4d685ae3fd1a752a0b79a10a6cf288c8a26",
|
||||
"0x689c7f32af0a20de771b9c03efeb6304b08a421cbc2f178b63cd284f3d74407f",
|
||||
"0x0375180a004265f4a38946353455c221785c3f6da1dcbde2c09c373fa42c434c",
|
||||
"0x764f8f063124e8226a65af4823b260354924781b339a93f6eeb0622e10333741",
|
||||
"0xd0a28ce8c50017ad2e0bf1c1f8193792228b879688f01354552e656272bd7936",
|
||||
"0x20b12fa78b655cce826e87bd18cf938917d37c306cb620afef671b0548b1e1d0",
|
||||
"0xc94540910d93236aff53413af46597dcb51c02508f14bf81817966ef32799c00",
|
||||
"0xeeda2d6df1baa5dd3cf904c4402e4e99aaaaa16b6f3a0832bffad5492fd9e725",
|
||||
"0x74de84a1158dfb1af0c1478cf0b048ae8b0ae00139588e91d37a6874b524522b",
|
||||
"0xe9c92a1b7b298d7222890fffbd5ae4d2f8a8e0c5519cd06c3e34fd94b1f12767",
|
||||
"0x18261f839aab59220f72e4e4bfa7a8dde2d3c5cd8c0179d2ff32a151f7af92c2",
|
||||
"0x35fd53473534a3bdbf0ada29529991bfe6ac1865cc6786306b92dc26a6aa8116",
|
||||
"0x6f40f093a08a00eefae4cb848462ba663b62f089005acb49a8f5ee3f1a767375",
|
||||
"0xb0d49e32ac2ddef6bf0729ce9212c4bcc053aaa7cf8dd6649247749bab68cfac",
|
||||
"0xb616c68f680b5cc9be3fc5bca40621514109dbc1316b848f1f3ce18b05e76d33",
|
||||
"0x3ac8fe2f016f98eaa25451e36ce4fcfcbd160c0306c57f2edea049cdf541538a",
|
||||
"0xb45e54eca70d4943eecaebfef3dc2219e79bdc71bddaec6adf53a1d058a65a30",
|
||||
"0x74284120c5fa1ddcb7c294533eedd0b1ca2703626b7361543cb8e2a922177aae",
|
||||
"0x8b15208a8b5d6ddfbe8b09148d497a5e3fc267b8f1d24272814d72f4826f8e88",
|
||||
"0x3f9d4dcd96d5c902d4ef5655c10620c3e5a25edfa6fa093b0546d05c7c724d8c",
|
||||
"0xf91ef06068659865a7c94e955f9c01ba4794214ebab33c9ec7030b2dfa47604a",
|
||||
"0xadd5bb3d2f06ada2edb35754833e1bf1e317edff3e33535e135e67b4e4c5fdca",
|
||||
"0x5aeb51beab2c98d3f77f2f04a39c2dfaed3ff759de9f5c16d4d88692a95eca60",
|
||||
"0xeab1ab2c49609df8e29041ffefea082f92941aefae697fd915b9aeee8665c57b",
|
||||
"0xbcf847e97f7f6fa5a16075ea54a67254e21fadeaa38d7aa42d16f223fd179faa",
|
||||
"0x07f25413e56e9dfbd9bedf4b0676755f0cdbbf10b8f13ac7ef360bef7ac905d1",
|
||||
"0x373e2f4dca323c9c4b4cd0cf4a1eb04ce7fd4d7548078200d9ffde2e3fa4cee7",
|
||||
"0x5b9fd47a0d9cb386ccdcb2755934bfb8b27be896e52afaf18a0d130bcdff5432",
|
||||
"0x1050a77797e0fc3a98c1d172496b8a3bbb2b045ebaa6b8b4af4e1542180f464c",
|
||||
"0xea29629a5b08050c92412a25506d4d6dd8ea0f6bd8c962422d8f4913090a6d2c",
|
||||
"0x1cc76b2b9f505bc358df15e285ac7cdde0009a2a19de9fcb5a44156ff76c5585",
|
||||
"0x03cbbc18173700023643a8d6d7ff57cb0503336794c5fbe0b705a95034b7af80",
|
||||
"0x9e2a5b70615a5c057d2956ac21838616ffd5cfb26fdf7398c4ad988a8cbc27ed",
|
||||
"0xb2ef5e7c15e169ad2ec00e254415f4fa6c1f0635f728a98724dca4335e1c7801",
|
||||
"0x50f9e432ed8c0c999685735ad95a4c2b3e0c0002d1159056392ed541ddca9b11",
|
||||
"0x40ecd3140c4c8b02ce66489b39842d92ca64d05c30a9eddbfe675dded3fb6f3f",
|
||||
"0xa1417d5ef7d185323ae3452fd99d54d5336f69ff866cfba06838da5efe273ebc",
|
||||
"0x93b51cb9e7c9ca4e5f67fae55992ef6b0869c8c2effc8d244791cd2275f5f136",
|
||||
"0xd9889fbd8c71e14316b5dfd46a6d049ec05127e5d3db6f0a31a935cb86b42d0f",
|
||||
"0x384e1275612d71431d80d155015010e22b8b14a0648328bf1b32f92b1673308b",
|
||||
"0x5eeac9b703836463fc0019c1b6f4be32282f4ade6778f897f6cf9d4c33e16085",
|
||||
"0x2bdd040915ac28a0a604b727f062cf49fd413c44bcfaa2cc5eaaa9224248ef51",
|
||||
"0xd7c85280a461c43df6c82f6ef60a973f2581c428394996191eeaa0d06a4b6473",
|
||||
"0xe57d7c71a989601a066f8447a5be928ad0ce47d5413eceb709761654a30667e4",
|
||||
"0xe1514ee44d1db8307cc08177a343887b5bd843cc510c5153b7f251aa10704f87",
|
||||
"0x2898a69c885bb4cfcffa45a8aa63a8e81a40d4e3a7e1ff218ca3b4c70b836e08",
|
||||
"0x27b66b51bb80e11582319b2fe176490daff05f0ce72a9dbfe79691676a455e0c",
|
||||
"0x321d7bade5b8a1adee64bb0362620d99a5528831cdc0f1bd0258c9d66e4515f1",
|
||||
"0x0a5443109753ff0845752dc998e82148d1de44d8347e51accd03cdbdcf405acd",
|
||||
"0x1ef3a558361ee68b83346d40624b13d3170519e10dd18f60b6c5d7804f3c2d1b",
|
||||
"0xf81fadde2aa798e6c151b35f764009d754f01aa0d8dacdd1a8f3109bd5d711d7",
|
||||
"0x1af5b4d637429fab034b33b5fb3add567b5896608bcdc9e8d86a7d7ce762b4c2",
|
||||
"0x8dcae50013fcabdc708c7b99c46fb4a68c75971775c135b7f7727bdf8db645a2",
|
||||
"0x74dd3719b6229c2f675e41bae47aa0de9587608e8ad76e9dd911d695cbe3727a",
|
||||
"0xca02fb569c275518e1cb95018a3b67dde118e82ade5cc9a43e118afa8da5e3d4",
|
||||
"0xd5a890bef2beb2920a7ac22be90d0ed203dcf6b37ed0b3d2cea1fcc8f68c6d98",
|
||||
"0x917c9cc04ac1f8afae96f0dc9b49161c352ed4e1da970e17d52fca31b8c1978a",
|
||||
"0x009f16eb012717beb87fcc2b4417c8096a621fddc2421d02d84d0bfe92cd3587",
|
||||
"0xe5ff9e2a1ffbcf1f53cf716b7caaa1317151ed8b81bd641bcf41eeadcdb0790f",
|
||||
"0x2dfd67dc149772d4aa52588315df62edbc8a9340f2b3afb367f7f1564c1b8503",
|
||||
"0x830df571a176933f6a72ac634933d61e602f744d1e3a046b7b639c9d2110580c",
|
||||
"0xb2a030fd70ad2290c69e9b41220c14800d9adc33d7f8af049120fc6526a654d4",
|
||||
"0x8a013c2432c60aa6315b1adc7155dd022df24129106cccbdf463273051ee0efc",
|
||||
"0x55040dc6b554877d752f2f0bf0d97f71b34583b3d939587106affdacaf5d7c0a",
|
||||
"0x251817e5c81aba6d675d47d688f19d5cb6957cea13ef3e15c66a6573b84af432",
|
||||
"0x708cc1d141308870ea3ac36e5781cbfa3b5af327c565231123496354b5a9e74b",
|
||||
"0x4efb2006e58b45c648d27654d45f1f797d4798217b2d0b54958fc576f115d81c",
|
||||
"0x7d1bc87fd32a1b2ce74fe3784be5c0fe2e625ceac523ad55da7ebcd3cd1cb94f",
|
||||
"0x575cc8bf8070ea53a54d027cb7d42eec9dffb85489013634350a96a434cb498b",
|
||||
"0xc69812969e85bcd2e7e048b4323a726691c78d1902c1f1dbdd3893c11b9df8f6",
|
||||
"0x6193928c0a4e47c9409c1af5d945a8c92c9e28a76570dfaaecfdda8071d6558d",
|
||||
"0xb8982114b6b5da8849c27ee7d23280e15aa780248ebd36e5d364f2a05ae1fe45",
|
||||
"0x49577950e5a3d4a06629686f9353adecdad6670fc9f4e6d3eaf6735296cc6775",
|
||||
"0x6444155176ebe3b62f028ad79f058271d5b317360c0b97b7fe8c2a642da88229",
|
||||
"0x9a3f0adf9c7b9380f60baf1d524590bec23b4d3790b3909ec8da3e79303252c7",
|
||||
"0x591f122777ae7a313b6c4ba8c052d483f2aa3a687b5d85ed39e19d7e0c0e6de2",
|
||||
"0xe3d68466d0747ab6245e5d8620eaae080a0f3c2aa34a56defe8adaef56d5474a",
|
||||
"0x8d0f53bb5f7610133f04a763263815e092e43b0016369866e959d22eca466d85",
|
||||
"0x8c8f0fff76977593112a64826f15ec0e909d9a1f1589e121a37f73d881e6b696",
|
||||
"0x9ab1411e7ef5b295ab1a9dfe4ee1cd1a740af5b7e4b0a0e9c4a5f37e803c7c94"
|
||||
]
|
||||
},
|
||||
"accounts": {
|
||||
"0x0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
|
||||
"0x0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
|
||||
"0x0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
|
||||
"0x0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
|
||||
"0x0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": 5067000, "pricing": { "modexp": { "divisor": 20 } } } },
|
||||
"0x0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": 5067000, "pricing": { "linear": { "base": 500, "word": 0 } } } },
|
||||
"0x0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": 5067000, "pricing": { "linear": { "base": 40000, "word": 0 } } } },
|
||||
"0x0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": 5067000, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } },
|
||||
"0x00521965e7bd230323c423d96c657db5b79d099f": { "balance": "1606938044258990275541962092341162602522202993782792835301376" }
|
||||
"0x0000000000000000000000000000000000000001": {
|
||||
"balance": "0x1",
|
||||
"builtin": {
|
||||
"name": "ecrecover",
|
||||
"pricing": {
|
||||
"linear": {
|
||||
"base": 3000,
|
||||
"word": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0x0000000000000000000000000000000000000002": {
|
||||
"balance": "0x1",
|
||||
"builtin": {
|
||||
"name": "sha256",
|
||||
"pricing": {
|
||||
"linear": {
|
||||
"base": 60,
|
||||
"word": 12
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0x0000000000000000000000000000000000000003": {
|
||||
"balance": "0x1",
|
||||
"builtin": {
|
||||
"name": "ripemd160",
|
||||
"pricing": {
|
||||
"linear": {
|
||||
"base": 600,
|
||||
"word": 120
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0x0000000000000000000000000000000000000004": {
|
||||
"balance": "0x1",
|
||||
"builtin": {
|
||||
"name": "identity",
|
||||
"pricing": {
|
||||
"linear": {
|
||||
"base": 15,
|
||||
"word": 3
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0x0000000000000000000000000000000000000005": {
|
||||
"builtin": {
|
||||
"name": "modexp",
|
||||
"activate_at": "0x4d50f8",
|
||||
"pricing": {
|
||||
"modexp": {
|
||||
"divisor": 20
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0x0000000000000000000000000000000000000006": {
|
||||
"builtin": {
|
||||
"name": "alt_bn128_add",
|
||||
"activate_at": "0x4d50f8",
|
||||
"pricing": {
|
||||
"linear": {
|
||||
"base": 500,
|
||||
"word": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0x0000000000000000000000000000000000000007": {
|
||||
"builtin": {
|
||||
"name": "alt_bn128_mul",
|
||||
"activate_at": "0x4d50f8",
|
||||
"pricing": {
|
||||
"linear": {
|
||||
"base": 40000,
|
||||
"word": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0x0000000000000000000000000000000000000008": {
|
||||
"builtin": {
|
||||
"name": "alt_bn128_pairing",
|
||||
"activate_at": "0x4d50f8",
|
||||
"pricing": {
|
||||
"alt_bn128_pairing": {
|
||||
"base": 100000,
|
||||
"pair": 80000
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0x00521965e7bd230323c423d96c657db5b79d099f": {
|
||||
"balance": "1606938044258990275541962092341162602522202993782792835301376"
|
||||
}
|
||||
},
|
||||
"nodes": [
|
||||
"enode://56abaf065581a5985b8c5f4f88bd202526482761ba10be9bfdcd14846dd01f652ec33fde0f8c0fd1db19b59a4c04465681fcef50e11380ca88d25996191c52de@40.71.221.215:30303",
|
||||
"enode://d07827483dc47b368eaf88454fb04b41b7452cf454e194e2bd4c14f98a3278fed5d819dbecd0d010407fc7688d941ee1e58d4f9c6354d3da3be92f55c17d7ce3@52.166.117.77:30303",
|
||||
"enode://8fa162563a8e5a05eef3e1cd5abc5828c71344f7277bb788a395cce4a0e30baf2b34b92fe0b2dbbba2313ee40236bae2aab3c9811941b9f5a7e8e90aaa27ecba@52.165.239.18:30303",
|
||||
"enode://7e2e7f00784f516939f94e22bdc6cf96153603ca2b5df1c7cc0f90a38e7a2f218ffb1c05b156835e8b49086d11fdd1b3e2965be16baa55204167aa9bf536a4d9@52.243.47.56:30303",
|
||||
"enode://0518a3d35d4a7b3e8c433e7ffd2355d84a1304ceb5ef349787b556197f0c87fad09daed760635b97d52179d645d3e6d16a37d2cc0a9945c2ddf585684beb39ac@40.68.248.100:30303"
|
||||
"enode://38e6e7fd416293ed120d567a2675fe078c0205ab0671abf16982ce969823bd1f3443d590c18b321dfae7dcbe1f6ba98ef8702f255c3c9822a188abb82c53adca@51.77.66.187:30303",
|
||||
"enode://6f289111f7c77c68651b0f4803c3a47bcec801f9c618bb41231a1a24a6dbb9c76f2fdb63ba7a21357c41ebb7f6922c17397c1b5c8f71f7d3ef7965505d4945de@144.217.72.209:30303",
|
||||
"enode://b6340eb94c3db1362ee517801389fe21cce6354275376b1006f8ce84f8a5cfa2b836268b3727be9db7cd3e581f356f39da39418c4ec1d63d959abc235d99cd86@145.239.7.213:30303"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -10,12 +10,7 @@
|
||||
"homesteadTransition":"0x118c30",
|
||||
"eip100bTransition":"0x7fffffffffffff",
|
||||
"blockReward":"0x1105a0185b50a80000",
|
||||
"mcip3Transition":"0x00",
|
||||
"mcip3MinerReward":"0xd8d726b7177a80000",
|
||||
"mcip3UbiReward":"0x2b5e3af16b1880000",
|
||||
"mcip3UbiContract":"0x00efdd5883ec628983e9063c7d969fe268bbf310",
|
||||
"mcip3DevReward":"0xc249fdd327780000",
|
||||
"mcip3DevContract":"0x00756cf8159095948496617f5fb17ed95059f536"
|
||||
"blockRewardContractCode": "0x6080604052600436106100405763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663f91c28988114610045575b600080fd5b34801561005157600080fd5b50610071602460048035828101929082013591813591820191013561010a565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156100b557818101518382015260200161009d565b50505050905001838103825284818151815260200191508051906020019060200280838360005b838110156100f45781810151838201526020016100dc565b5050505090500194505050505060405180910390f35b6060808080600080803373fffffffffffffffffffffffffffffffffffffffe1461013357600080fd5b89881461013f57600080fd5b60408051600380825260808201909252906020820160608038833950506040805160038082526080820190925292975090506020820160608038833901905050935072efdd5883ec628983e9063c7d969fe268bbf3108560018151811015156101a457fe5b73ffffffffffffffffffffffffffffffffffffffff90921660209283029091019091015283516802b5e3af16b188000090859060019081106101e257fe5b60209081029091010152845172756cf8159095948496617f5fb17ed95059f536908690600290811061021057fe5b73ffffffffffffffffffffffffffffffffffffffff909216602092830290910190910152835167c249fdd327780000908590600290811061024d57fe5b60209081029091010152600092505b898310156103b75788888481811061027057fe5b9050602002013561ffff1661ffff166000141561030c578a8a8481811061029357fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff168560008151811015156102bf57fe5b73ffffffffffffffffffffffffffffffffffffffff9092166020928302909101909101528351680d8d726b7177a8000090859060009081106102fd57fe5b602090810290910101526103ac565b606489898581811061031a57fe5b9050602002013561ffff1661ffff161015156103ac57606489898581811061033e57fe5b9050602002013561ffff1603915060038260080361ffff16681105a0185b50a80000029060020a9004905061039d858c8c86818110151561037b57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff166103c8565b94506103a9848261049f565b93505b60019092019161025c565b509299919850909650505050505050565b606080600084516001016040519080825280602002602001820160405280156103fb578160200160208202803883390190505b509150600090505b845181101561045e57848181518110151561041a57fe5b90602001906020020151828281518110151561043257fe5b73ffffffffffffffffffffffffffffffffffffffff909216602092830290910190910152600101610403565b8382600184510381518110151561047157fe5b73ffffffffffffffffffffffffffffffffffffffff9290921660209283029190910190910152509392505050565b606080600084516001016040519080825280602002602001820160405280156104d2578160200160208202803883390190505b509150600090505b845181101561051b5784818151811015156104f157fe5b90602001906020020151828281518110151561050957fe5b602090810290910101526001016104da565b8382600184510381518110151561052e57fe5b60209081029190910101525093925050505600a165627a7a72305820c9ab92a56245040e76af5fc4f3ac4cf4315336b503db06677c21aa1e00aaa8e20029"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,162 +0,0 @@
|
||||
{
|
||||
"name": "Musicoin Byzantium Test",
|
||||
"dataDir": "mcip6test",
|
||||
"engine": {
|
||||
"Ethash": {
|
||||
"params": {
|
||||
"minimumDifficulty": "0x020000",
|
||||
"difficultyBoundDivisor": "0x0800",
|
||||
"durationLimit": "0x0d",
|
||||
"homesteadTransition": "0x17",
|
||||
"eip100bTransition": "0x2a",
|
||||
"blockReward": "0x1105a0185b50a80000",
|
||||
"mcip3Transition": "0x17",
|
||||
"mcip3MinerReward": "0xd8d726b7177a80000",
|
||||
"mcip3UbiReward": "0x2b5e3af16b1880000",
|
||||
"mcip3UbiContract": "0x00efdd5883ec628983e9063c7d969fe268bbf310",
|
||||
"mcip3DevReward": "0xc249fdd327780000",
|
||||
"mcip3DevContract": "0x00756cf8159095948496617f5fb17ed95059f536",
|
||||
"difficultyBombDelays": {
|
||||
"0x2a": 3000000
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"params": {
|
||||
"gasLimitBoundDivisor": "0x0400",
|
||||
"registrar": "0x5C271c4C9A67E7D73b7b3669d47504741354f21D",
|
||||
"accountStartNonce": "0x00",
|
||||
"maximumExtraDataSize": "0x20",
|
||||
"minGasLimit": "0x1388",
|
||||
"networkID": "0x76740c",
|
||||
"forkBlock": "0x2b",
|
||||
"forkCanonHash": "0x23c3171e864a5d513a3ef85e4cf86dac4cc36b89e5b8e63bf0ebcca68b9e43c9",
|
||||
"eip150Transition": "0x2a",
|
||||
"eip160Transition": "0x7fffffffffffff",
|
||||
"eip161abcTransition": "0x7fffffffffffff",
|
||||
"eip161dTransition": "0x7fffffffffffff",
|
||||
"eip98Transition": "0x7fffffffffffff",
|
||||
"eip140Transition": "0x2a",
|
||||
"eip155Transition": "0x2a",
|
||||
"eip211Transition": "0x2a",
|
||||
"eip214Transition": "0x2a",
|
||||
"eip658Transition": "0x2a",
|
||||
"maxCodeSize": "0x6000",
|
||||
"maxCodeSizeTransition": "0x7fffffffffffff"
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
"ethereum": {
|
||||
"nonce": "0x000000000000002a",
|
||||
"mixHash": "0x00000000000000000000000000000000000000647572616c65787365646c6578"
|
||||
}
|
||||
},
|
||||
"difficulty": "0x3d0900",
|
||||
"author": "0x0000000000000000000000000000000000000000",
|
||||
"timestamp": "0x00",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"extraData": "",
|
||||
"gasLimit": "0x7a1200"
|
||||
},
|
||||
"nodes": [
|
||||
"enode://5ddc110733f6d34101973cdef3f9b43484159acf6f816d3b1ee92bc3c98ea453e857bb1207edf0ec0242008ab3a0f9f05eeaee99d47bd414c08a5bdf4847de13@176.9.3.148:30303",
|
||||
"enode://38f074f4db8e64dfbaf87984bf290eef67772a901a7113d1b62f36216be152b8450c393d6fc562a5e38f04f99bc8f439a99010a230b1d92dc1df43bf0bd00615@176.9.3.148:30403"
|
||||
],
|
||||
"accounts": {
|
||||
"0000000000000000000000000000000000000001": {
|
||||
"balance": "1",
|
||||
"builtin": {
|
||||
"name": "ecrecover",
|
||||
"pricing": {
|
||||
"linear": {
|
||||
"base": 3000,
|
||||
"word": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000002": {
|
||||
"balance": "1",
|
||||
"builtin": {
|
||||
"name": "sha256",
|
||||
"pricing": {
|
||||
"linear": {
|
||||
"base": 60,
|
||||
"word": 12
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000003": {
|
||||
"balance": "1",
|
||||
"builtin": {
|
||||
"name": "ripemd160",
|
||||
"pricing": {
|
||||
"linear": {
|
||||
"base": 600,
|
||||
"word": 120
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000004": {
|
||||
"balance": "1",
|
||||
"builtin": {
|
||||
"name": "identity",
|
||||
"pricing": {
|
||||
"linear": {
|
||||
"base": 15,
|
||||
"word": 3
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000005": {
|
||||
"builtin": {
|
||||
"name": "modexp",
|
||||
"activate_at": "0x2a",
|
||||
"pricing": {
|
||||
"modexp": {
|
||||
"divisor": 20
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000006": {
|
||||
"builtin": {
|
||||
"name": "alt_bn128_add",
|
||||
"activate_at": "0x2a",
|
||||
"pricing": {
|
||||
"linear": {
|
||||
"base": 500,
|
||||
"word": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000007": {
|
||||
"builtin": {
|
||||
"name": "alt_bn128_mul",
|
||||
"activate_at": "0x2a",
|
||||
"pricing": {
|
||||
"linear": {
|
||||
"base": 40000,
|
||||
"word": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"0000000000000000000000000000000000000008": {
|
||||
"builtin": {
|
||||
"name": "alt_bn128_pairing",
|
||||
"activate_at": "0x2a",
|
||||
"pricing": {
|
||||
"alt_bn128_pairing": {
|
||||
"base": 100000,
|
||||
"pair": 80000
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,12 +10,8 @@
|
||||
"homesteadTransition":"0x118c30",
|
||||
"eip100bTransition":"0x21e88e",
|
||||
"blockReward":"0x1105a0185b50a80000",
|
||||
"mcip3Transition":"0x124f81",
|
||||
"mcip3MinerReward":"0xd8d726b7177a80000",
|
||||
"mcip3UbiReward":"0x2b5e3af16b1880000",
|
||||
"mcip3UbiContract":"0x00efdd5883ec628983e9063c7d969fe268bbf310",
|
||||
"mcip3DevReward":"0xc249fdd327780000",
|
||||
"mcip3DevContract":"0x00756cf8159095948496617f5fb17ed95059f536",
|
||||
"blockRewardContractTransition": "0x124f81",
|
||||
"blockRewardContractCode": "0x6080604052600436106100405763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663f91c28988114610045575b600080fd5b34801561005157600080fd5b50610071602460048035828101929082013591813591820191013561010a565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156100b557818101518382015260200161009d565b50505050905001838103825284818151815260200191508051906020019060200280838360005b838110156100f45781810151838201526020016100dc565b5050505090500194505050505060405180910390f35b6060808080600080803373fffffffffffffffffffffffffffffffffffffffe1461013357600080fd5b89881461013f57600080fd5b60408051600380825260808201909252906020820160608038833950506040805160038082526080820190925292975090506020820160608038833901905050935072efdd5883ec628983e9063c7d969fe268bbf3108560018151811015156101a457fe5b73ffffffffffffffffffffffffffffffffffffffff90921660209283029091019091015283516802b5e3af16b188000090859060019081106101e257fe5b60209081029091010152845172756cf8159095948496617f5fb17ed95059f536908690600290811061021057fe5b73ffffffffffffffffffffffffffffffffffffffff909216602092830290910190910152835167c249fdd327780000908590600290811061024d57fe5b60209081029091010152600092505b898310156103b75788888481811061027057fe5b9050602002013561ffff1661ffff166000141561030c578a8a8481811061029357fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff168560008151811015156102bf57fe5b73ffffffffffffffffffffffffffffffffffffffff9092166020928302909101909101528351680d8d726b7177a8000090859060009081106102fd57fe5b602090810290910101526103ac565b606489898581811061031a57fe5b9050602002013561ffff1661ffff161015156103ac57606489898581811061033e57fe5b9050602002013561ffff1603915060038260080361ffff16681105a0185b50a80000029060020a9004905061039d858c8c86818110151561037b57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff166103c8565b94506103a9848261049f565b93505b60019092019161025c565b509299919850909650505050505050565b606080600084516001016040519080825280602002602001820160405280156103fb578160200160208202803883390190505b509150600090505b845181101561045e57848181518110151561041a57fe5b90602001906020020151828281518110151561043257fe5b73ffffffffffffffffffffffffffffffffffffffff909216602092830290910190910152600101610403565b8382600184510381518110151561047157fe5b73ffffffffffffffffffffffffffffffffffffffff9290921660209283029190910190910152509392505050565b606080600084516001016040519080825280602002602001820160405280156104d2578160200160208202803883390190505b509150600090505b845181101561051b5784818151811015156104f157fe5b90602001906020020151828281518110151561050957fe5b602090810290910101526001016104da565b8382600184510381518110151561052e57fe5b60209081029190910101525093925050505600a165627a7a72305820c9ab92a56245040e76af5fc4f3ac4cf4315336b503db06677c21aa1e00aaa8e20029",
|
||||
"difficultyBombDelays": {
|
||||
"0x21e88e": 3000000
|
||||
}
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
{
|
||||
"name": "Olympic",
|
||||
"engine": {
|
||||
"Ethash": {
|
||||
"params": {
|
||||
"minimumDifficulty": "0x020000",
|
||||
"difficultyBoundDivisor": "0x0800",
|
||||
"durationLimit": "0x08",
|
||||
"blockReward": "0x14D1120D7B160000",
|
||||
"homesteadTransition": "0x7fffffffffffffff"
|
||||
}
|
||||
}
|
||||
},
|
||||
"params": {
|
||||
"gasLimitBoundDivisor": "0x0400",
|
||||
"registrar": "5e70c0bbcd5636e0f9f9316e9f8633feb64d4050",
|
||||
"accountStartNonce": "0x00",
|
||||
"maximumExtraDataSize": "0x0400",
|
||||
"minGasLimit": "125000",
|
||||
"networkID" : "0x0",
|
||||
"eip150Transition": "0x7fffffffffffffff",
|
||||
"eip160Transition": "0x7fffffffffffffff",
|
||||
"eip161abcTransition": "0x7fffffffffffffff",
|
||||
"eip161dTransition": "0x7fffffffffffffff",
|
||||
"eip98Transition": "0x7fffffffffffff",
|
||||
"eip155Transition": "0x7fffffffffffffff"
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
"ethereum": {
|
||||
"nonce": "0x000000000000002a",
|
||||
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
},
|
||||
"difficulty": "0x20000",
|
||||
"author": "0x0000000000000000000000000000000000000000",
|
||||
"timestamp": "0x00",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"extraData": "0x",
|
||||
"gasLimit": "0x2fefd8"
|
||||
},
|
||||
"accounts": {
|
||||
"0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
|
||||
"0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
|
||||
"0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
|
||||
"0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
|
||||
"dbdbdb2cbd23b783741e8d7fcf51e459b497e4a6": { "balance": "1606938044258990275541962092341162602522202993782792835301376" },
|
||||
"e6716f9544a56c530d868e4bfbacb172315bdead": { "balance": "1606938044258990275541962092341162602522202993782792835301376" },
|
||||
"b9c015918bdaba24b4ff057a92a3873d6eb201be": { "balance": "1606938044258990275541962092341162602522202993782792835301376" },
|
||||
"1a26338f0d905e295fccb71fa9ea849ffa12aaf4": { "balance": "1606938044258990275541962092341162602522202993782792835301376" },
|
||||
"2ef47100e0787b915105fd5e3f4ff6752079d5cb": { "balance": "1606938044258990275541962092341162602522202993782792835301376" },
|
||||
"cd2a3d9f938e13cd947ec05abc7fe734df8dd826": { "balance": "1606938044258990275541962092341162602522202993782792835301376" },
|
||||
"6c386a4b26f73c802f34673f7248bb118f97424a": { "balance": "1606938044258990275541962092341162602522202993782792835301376" },
|
||||
"e4157b34ea9615cfbde6b4fda419828124b70c78": { "balance": "1606938044258990275541962092341162602522202993782792835301376" }
|
||||
}
|
||||
}
|
||||
@@ -15,9 +15,14 @@
|
||||
},
|
||||
"772000": {
|
||||
"safeContract": "0x83451c8bc04d4ee9745ccc58edfab88037bc48cc"
|
||||
},
|
||||
"5329160": {
|
||||
"safeContract": "0xa105Db0e6671C7B5f4f350ff1Af6460E6C696e71"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"blockRewardContractAddress": "0x4d0153D434384128D17243409e02fca1B3EE21D6",
|
||||
"blockRewardContractTransition": 5761140
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -45,12 +50,10 @@
|
||||
"enode://6e3d1b39cbd2a9c4f053a27e68fd90d0bac83691dfdc4a13c59f2555078a71e63c5daaee5a82aa6db500512760a5456f86076bf8bbe8011c27c82ed7d6f5fb26@45.77.140.210:30303",
|
||||
"enode://f4698ad485a027497e1cc992bb5f7cecee2b32a44c47202738d8d0eecfab719541988d0cbcbc5ea94c6c959e5cddeb85fc6ae75fb63dc3bf87cdbe9e6f615e9d@206.156.242.64:30303",
|
||||
"enode://31dffed97f8fed1f34fe66453280a89cbeeda60cf28f6fbb212ebbefd7c7566a02c1c7d5c00bbbb49b9fa8a49f157e0f786f379ca9bcbf2fea24de70d70a22b6@206.156.242.61:30303",
|
||||
"enode://efe1a701595b7bfc20cc71a70dcdf1d731a5ca618cbc1bd0059edc6658d5958a2b243cc88112c7ded48f3d331a26a6a76b4d3f4a51260b5fb5d13f798e5786f0@206.156.242.62:30303",
|
||||
"enode://6bdc7553ab2e4914cb47774c1e6d8c8f47ac7c3981891f85f65d06f208ea1bc4d3bf982b330950e0a0cd127efd7145c4df7113159a1d4a06ed722e6c16d0ac6c@45.32.215.190:30303",
|
||||
"enode://872d82a24144bc007658fb6fac0dcdfb9b63aeb05ef563a06d0186f2d1e5ffbfc5c4f1244891a8a86ef70682b9d24382e654b305224883698862e2df647a4d23@45.76.236.247:30303",
|
||||
"enode://b11fbc6cde81c80be69508aca8ffea8460680a25a9c151b683293f8617282062b8e8e139bf91e88cedf60068a3cf927b0d48832fda5169b58a8f7ce442de6fb4@206.189.76.132:30303",
|
||||
"enode://96678da10ac83769ab3f63114a41b57b700476c5ac02719b878fa89909a936551bb7609aa09b068bf89903206fa03f23e1b5b9117ca278de304c2570b87dcb27@18.208.191.114:30303",
|
||||
"enode://47ee6bc6312210caa0087a5754221f7666e37ab2d5c10cfe386ecdf9e5f935fc55726b37d10f0eaf493f762a270445d3e6d569891c328759b8baeb39f6f6ed2d@34.224.215.151:30303"
|
||||
"enode://96678da10ac83769ab3f63114a41b57b700476c5ac02719b878fa89909a936551bb7609aa09b068bf89903206fa03f23e1b5b9117ca278de304c2570b87dcb27@35.175.15.164:30303"
|
||||
],
|
||||
"accounts": {
|
||||
"0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x0", "pricing": { "modexp": { "divisor": 20 } } } },
|
||||
|
||||
@@ -18,9 +18,14 @@
|
||||
},
|
||||
"509355": {
|
||||
"safeContract": "0x03048F666359CFD3C74a1A5b9a97848BF71d5038"
|
||||
},
|
||||
"4622420": {
|
||||
"safeContract": "0x4c6a159659CCcb033F4b2e2Be0C16ACC62b89DDB"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"blockRewardContractAddress": "0x3145197AD50D7083D0222DE4fCCf67d9BD05C30D",
|
||||
"blockRewardContractTransition": 4639000
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -32,7 +37,12 @@
|
||||
"eip140Transition": "0x0",
|
||||
"eip211Transition": "0x0",
|
||||
"eip214Transition": "0x0",
|
||||
"eip658Transition": "0x0"
|
||||
"eip658Transition": "0x0",
|
||||
"eip145Transition": 6464300,
|
||||
"eip1014Transition": 6464300,
|
||||
"eip1052Transition": 6464300,
|
||||
"eip1283Transition": 6464300,
|
||||
"eip1283DisableTransition": 7026400
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
@@ -46,19 +56,12 @@
|
||||
},
|
||||
"nodes": [
|
||||
"enode://8e0af07c86ec36590bb6368e7ad0c45b6dc658f5fb66ec68889a614affddda5e021bd513bcf4fb2fae4a3bbe08cf0de84f037cd58478a89665dfce1ded2595c7@34.236.37.74:30303",
|
||||
"enode://0171db265a569636372566e86cb7a69306fe5c15a8e2ed5bed4010012fa1d146ae4918a688cf1bd3fd98e8c2d5c3705d68ff941c88ab974ff52c7fc8606ce2f8@35.168.201.160:30303",
|
||||
"enode://9a4a3788471af17a8346da7fc41057f037da692d4fad0ac5023fc0c88cf64666d74ee9f6396012eec98cd6bc772418b42dddd823a38e359bbfdc4fc93ba38de8@34.229.128.189:30303",
|
||||
"enode://881e56dc71472376b65ddaad5e42ee73084c96eb368c1e219b4fbcd73ffa339703cca168b6620cb1eabb7b8dcfe72e563117670c7ce94298c20d04b709c65697@165.227.111.36:30303",
|
||||
"enode://8e3733fe1606b17dd743e7d4fdb7ec1e0b909aab3c5289beabcb36e9d3175ca05bb36a52589090d4899c85a9219622ea4cbb9541057b722be65241db557b51a8@52.201.214.63:30303",
|
||||
"enode://f1a5100a81cb73163ae450c584d06b1f644aa4fad4486c6aeb4c384b343c54bb66c744aa5f133af66ea1b25f0f4a454f04878f3e96ee4cd2390c047396d6357b@209.97.158.4:30303",
|
||||
"enode://0d1e0372f63a3f0b82d66635ea101ecc0f6797788a078805cc933dd93e6a22f7c9fa51ab4e2d21da02d04480ef19f3bbb9a2b41dd1c262085d295a354bb8b0f9@18.217.47.209:30303",
|
||||
"enode://ab083db73da15b3995ac9c68035cdb32901835a823cb848fccb672e43dd21f14428706118d6fe5b921d8e741f122f35aad0255bc86807b1d17bcfa1e86e40a14@165.227.37.104:30303",
|
||||
"enode://a2a8545ccceaa1152721a213e6aca912c6d89a37bc6eea73999fdb08a95c6f07a79057f7f41c75c128f58ed77a13985e5c33c8c50d6a3d60b50c43f5f69c1fcd@52.170.16.34:30303",
|
||||
"enode://8e0af07c86ec36590bb6368e7ad0c45b6dc658f5fb66ec68889a614affddda5e021bd513bcf4fb2fae4a3bbe08cf0de84f037cd58478a89665dfce1ded2595c7@34.236.37.74:30303",
|
||||
"enode://182ee200ca134dc4d6390f3d5aadbcd80df0f7f24335830335d142573eacce4eeb919d30e82c5df588034e167e6ba6dd11187502ac9264a71005127f6b146a99@159.203.95.241:30303",
|
||||
"enode://b022ff70b5fcaf9596ae5efed99a8198b4ae0578ee9d17b733609d803a75cef95d3a2a18e50dca9a7c3b26139f158c59eaf8b5fb8d1d331c9a46934a78acabe8@206.189.76.128:30303",
|
||||
"enode://4a16c9a597dad00c000523fc2f4302bb8bb7f05949ec0ea4a516f0c6de9e191662f650ab55ea2a05f5af0f0eeee879800074f7263328f09181c7156059b7b6b7@18.221.62.190:30303",
|
||||
"enode://6527003feb6b534a7fac297b92d2f368bdf679d8f489639006c78640bf3ead3cdbf88a88a7bec29e6e29510122f279adf094d1b1b6e9e5005c4584aeb482c4a0@35.172.215.190:30303",
|
||||
"enode://99f335f9dffe978f7a925590f011909f2db1a2b28b05a0dc10da47e285e3d20b2d827caee258607c707c5261d9ba5f7f5b899dd025315c0afbfd5536a91ccf73@18.209.18.86:30303"
|
||||
"enode://b022ff70b5fcaf9596ae5efed99a8198b4ae0578ee9d17b733609d803a75cef95d3a2a18e50dca9a7c3b26139f158c59eaf8b5fb8d1d331c9a46934a78acabe8@206.189.76.128:30303"
|
||||
],
|
||||
"accounts": {
|
||||
"0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x0", "pricing": { "modexp": { "divisor": 20 } } } },
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
65
ethcore/res/ethereum/st_peters_test.json
Normal file
65
ethcore/res/ethereum/st_peters_test.json
Normal file
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"name": "St. Peter's (test)",
|
||||
"engine": {
|
||||
"Ethash": {
|
||||
"params": {
|
||||
"minimumDifficulty": "0x020000",
|
||||
"difficultyBoundDivisor": "0x0800",
|
||||
"durationLimit": "0x0d",
|
||||
"blockReward": "0x1BC16D674EC80000",
|
||||
"homesteadTransition": "0x0",
|
||||
"eip100bTransition": "0x0",
|
||||
"difficultyBombDelays": {
|
||||
"0": 5000000
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"params": {
|
||||
"gasLimitBoundDivisor": "0x0400",
|
||||
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
|
||||
"accountStartNonce": "0x00",
|
||||
"maximumExtraDataSize": "0x20",
|
||||
"minGasLimit": "0x1388",
|
||||
"networkID" : "0x1",
|
||||
"maxCodeSize": 24576,
|
||||
"maxCodeSizeTransition": "0x0",
|
||||
"eip150Transition": "0x0",
|
||||
"eip160Transition": "0x0",
|
||||
"eip161abcTransition": "0x0",
|
||||
"eip161dTransition": "0x0",
|
||||
"eip140Transition": "0x0",
|
||||
"eip211Transition": "0x0",
|
||||
"eip214Transition": "0x0",
|
||||
"eip155Transition": "0x0",
|
||||
"eip658Transition": "0x0",
|
||||
"eip145Transition": "0x0",
|
||||
"eip1014Transition": "0x0",
|
||||
"eip1052Transition": "0x0",
|
||||
"eip1283DisableTransition": "0x0"
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
"ethereum": {
|
||||
"nonce": "0x0000000000000042",
|
||||
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
},
|
||||
"difficulty": "0x400000000",
|
||||
"author": "0x0000000000000000000000000000000000000000",
|
||||
"timestamp": "0x00",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
|
||||
"gasLimit": "0x1388"
|
||||
},
|
||||
"accounts": {
|
||||
"0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
|
||||
"0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
|
||||
"0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
|
||||
"0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
|
||||
"0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 20 } } } },
|
||||
"0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0x00", "pricing": { "linear": { "base": 500, "word": 0 } } } },
|
||||
"0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x00", "pricing": { "linear": { "base": 40000, "word": 0 } } } },
|
||||
"0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x00", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }
|
||||
}
|
||||
}
|
||||
Submodule ethcore/res/ethereum/tests updated: b8a21c1936...725dbc73a5
4
ethcore/res/ethereum/tests-issues/currents.json
Normal file
4
ethcore/res/ethereum/tests-issues/currents.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"block": [],
|
||||
"state": []
|
||||
}
|
||||
Submodule ethcore/res/wasm-tests updated: d17bfb6962...0edbf860ff
@@ -106,7 +106,13 @@ impl ClientService {
|
||||
info!("Configured for {} using {} engine", Colour::White.bold().paint(spec.name.clone()), Colour::Yellow.bold().paint(spec.engine.name()));
|
||||
|
||||
let pruning = config.pruning;
|
||||
let client = Client::new(config, &spec, blockchain_db.clone(), miner.clone(), io_service.channel())?;
|
||||
let client = Client::new(
|
||||
config,
|
||||
&spec,
|
||||
blockchain_db.clone(),
|
||||
miner.clone(),
|
||||
io_service.channel(),
|
||||
)?;
|
||||
miner.set_io_channel(io_service.channel());
|
||||
miner.set_in_chain_checker(&client.clone());
|
||||
|
||||
@@ -117,7 +123,7 @@ impl ClientService {
|
||||
pruning: pruning,
|
||||
channel: io_service.channel(),
|
||||
snapshot_root: snapshot_path.into(),
|
||||
db_restore: client.clone(),
|
||||
client: client.clone(),
|
||||
};
|
||||
let snapshot = Arc::new(SnapshotService::new(snapshot_params)?);
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ impl Default for Factory {
|
||||
impl Factory {
|
||||
/// Create a read-only accountdb.
|
||||
/// This will panic when write operations are called.
|
||||
pub fn readonly<'db>(&self, db: &'db HashDB<KeccakHasher>, address_hash: H256) -> Box<HashDB<KeccakHasher> + 'db> {
|
||||
pub fn readonly<'db>(&self, db: &'db HashDB<KeccakHasher, DBValue>, address_hash: H256) -> Box<HashDB<KeccakHasher, DBValue> + 'db> {
|
||||
match *self {
|
||||
Factory::Mangled => Box::new(AccountDB::from_hash(db, address_hash)),
|
||||
Factory::Plain => Box::new(Wrapping(db)),
|
||||
@@ -66,7 +66,7 @@ impl Factory {
|
||||
}
|
||||
|
||||
/// Create a new mutable hashdb.
|
||||
pub fn create<'db>(&self, db: &'db mut HashDB<KeccakHasher>, address_hash: H256) -> Box<HashDB<KeccakHasher> + 'db> {
|
||||
pub fn create<'db>(&self, db: &'db mut HashDB<KeccakHasher, DBValue>, address_hash: H256) -> Box<HashDB<KeccakHasher, DBValue> + 'db> {
|
||||
match *self {
|
||||
Factory::Mangled => Box::new(AccountDBMut::from_hash(db, address_hash)),
|
||||
Factory::Plain => Box::new(WrappingMut(db)),
|
||||
@@ -78,19 +78,19 @@ impl Factory {
|
||||
/// DB backend wrapper for Account trie
|
||||
/// Transforms trie node keys for the database
|
||||
pub struct AccountDB<'db> {
|
||||
db: &'db HashDB<KeccakHasher>,
|
||||
db: &'db HashDB<KeccakHasher, DBValue>,
|
||||
address_hash: H256,
|
||||
}
|
||||
|
||||
impl<'db> AccountDB<'db> {
|
||||
/// Create a new AccountDB from an address.
|
||||
#[cfg(test)]
|
||||
pub fn new(db: &'db HashDB<KeccakHasher>, address: &Address) -> Self {
|
||||
pub fn new(db: &'db HashDB<KeccakHasher, DBValue>, address: &Address) -> Self {
|
||||
Self::from_hash(db, keccak(address))
|
||||
}
|
||||
|
||||
/// Create a new AcountDB from an address' hash.
|
||||
pub fn from_hash(db: &'db HashDB<KeccakHasher>, address_hash: H256) -> Self {
|
||||
pub fn from_hash(db: &'db HashDB<KeccakHasher, DBValue>, address_hash: H256) -> Self {
|
||||
AccountDB {
|
||||
db: db,
|
||||
address_hash: address_hash,
|
||||
@@ -98,12 +98,12 @@ impl<'db> AccountDB<'db> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'db> AsHashDB<KeccakHasher> for AccountDB<'db> {
|
||||
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self }
|
||||
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> { self }
|
||||
impl<'db> AsHashDB<KeccakHasher, DBValue> for AccountDB<'db> {
|
||||
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> { self }
|
||||
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> { self }
|
||||
}
|
||||
|
||||
impl<'db> HashDB<KeccakHasher> for AccountDB<'db> {
|
||||
impl<'db> HashDB<KeccakHasher, DBValue> for AccountDB<'db> {
|
||||
fn keys(&self) -> HashMap<H256, i32> {
|
||||
unimplemented!()
|
||||
}
|
||||
@@ -137,19 +137,19 @@ impl<'db> HashDB<KeccakHasher> for AccountDB<'db> {
|
||||
|
||||
/// DB backend wrapper for Account trie
|
||||
pub struct AccountDBMut<'db> {
|
||||
db: &'db mut HashDB<KeccakHasher>,
|
||||
db: &'db mut HashDB<KeccakHasher, DBValue>,
|
||||
address_hash: H256,
|
||||
}
|
||||
|
||||
impl<'db> AccountDBMut<'db> {
|
||||
/// Create a new AccountDB from an address.
|
||||
#[cfg(test)]
|
||||
pub fn new(db: &'db mut HashDB<KeccakHasher>, address: &Address) -> Self {
|
||||
pub fn new(db: &'db mut HashDB<KeccakHasher, DBValue>, address: &Address) -> Self {
|
||||
Self::from_hash(db, keccak(address))
|
||||
}
|
||||
|
||||
/// Create a new AcountDB from an address' hash.
|
||||
pub fn from_hash(db: &'db mut HashDB<KeccakHasher>, address_hash: H256) -> Self {
|
||||
pub fn from_hash(db: &'db mut HashDB<KeccakHasher, DBValue>, address_hash: H256) -> Self {
|
||||
AccountDBMut {
|
||||
db: db,
|
||||
address_hash: address_hash,
|
||||
@@ -162,7 +162,7 @@ impl<'db> AccountDBMut<'db> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'db> HashDB<KeccakHasher> for AccountDBMut<'db>{
|
||||
impl<'db> HashDB<KeccakHasher, DBValue> for AccountDBMut<'db>{
|
||||
fn keys(&self) -> HashMap<H256, i32> {
|
||||
unimplemented!()
|
||||
}
|
||||
@@ -208,19 +208,19 @@ impl<'db> HashDB<KeccakHasher> for AccountDBMut<'db>{
|
||||
}
|
||||
}
|
||||
|
||||
impl<'db> AsHashDB<KeccakHasher> for AccountDBMut<'db> {
|
||||
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self }
|
||||
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> { self }
|
||||
impl<'db> AsHashDB<KeccakHasher, DBValue> for AccountDBMut<'db> {
|
||||
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> { self }
|
||||
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> { self }
|
||||
}
|
||||
|
||||
struct Wrapping<'db>(&'db HashDB<KeccakHasher>);
|
||||
struct Wrapping<'db>(&'db HashDB<KeccakHasher, DBValue>);
|
||||
|
||||
impl<'db> AsHashDB<KeccakHasher> for Wrapping<'db> {
|
||||
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self }
|
||||
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> { self }
|
||||
impl<'db> AsHashDB<KeccakHasher, DBValue> for Wrapping<'db> {
|
||||
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> { self }
|
||||
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> { self }
|
||||
}
|
||||
|
||||
impl<'db> HashDB<KeccakHasher> for Wrapping<'db> {
|
||||
impl<'db> HashDB<KeccakHasher, DBValue> for Wrapping<'db> {
|
||||
fn keys(&self) -> HashMap<H256, i32> {
|
||||
unimplemented!()
|
||||
}
|
||||
@@ -252,13 +252,13 @@ impl<'db> HashDB<KeccakHasher> for Wrapping<'db> {
|
||||
}
|
||||
}
|
||||
|
||||
struct WrappingMut<'db>(&'db mut HashDB<KeccakHasher>);
|
||||
impl<'db> AsHashDB<KeccakHasher> for WrappingMut<'db> {
|
||||
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self }
|
||||
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> { self }
|
||||
struct WrappingMut<'db>(&'db mut HashDB<KeccakHasher, DBValue>);
|
||||
impl<'db> AsHashDB<KeccakHasher, DBValue> for WrappingMut<'db> {
|
||||
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> { self }
|
||||
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> { self }
|
||||
}
|
||||
|
||||
impl<'db> HashDB<KeccakHasher> for WrappingMut<'db>{
|
||||
impl<'db> HashDB<KeccakHasher, DBValue> for WrappingMut<'db>{
|
||||
fn keys(&self) -> HashMap<H256, i32> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
@@ -160,11 +160,6 @@ pub trait BlockProvider {
|
||||
.and_then(|n| body.view().localized_transaction_at(&address.block_hash, n, address.index)))
|
||||
}
|
||||
|
||||
/// Get transaction receipt.
|
||||
fn transaction_receipt(&self, address: &TransactionAddress) -> Option<Receipt> {
|
||||
self.block_receipts(&address.block_hash).and_then(|br| br.receipts.into_iter().nth(address.index))
|
||||
}
|
||||
|
||||
/// Get a list of transactions for a given block.
|
||||
/// Returns None if block does not exist.
|
||||
fn transactions(&self, hash: &H256) -> Option<Vec<LocalizedTransaction>> {
|
||||
@@ -234,6 +229,7 @@ pub struct BlockChain {
|
||||
|
||||
cache_man: Mutex<CacheManager<CacheId>>,
|
||||
|
||||
pending_best_ancient_block: RwLock<Option<Option<BestAncientBlock>>>,
|
||||
pending_best_block: RwLock<Option<BestBlock>>,
|
||||
pending_block_hashes: RwLock<HashMap<BlockNumber, H256>>,
|
||||
pending_block_details: RwLock<HashMap<H256, BlockDetails>>,
|
||||
@@ -543,6 +539,7 @@ impl BlockChain {
|
||||
block_receipts: RwLock::new(HashMap::new()),
|
||||
db: db.clone(),
|
||||
cache_man: Mutex::new(cache_man),
|
||||
pending_best_ancient_block: RwLock::new(None),
|
||||
pending_best_block: RwLock::new(None),
|
||||
pending_block_hashes: RwLock::new(HashMap::new()),
|
||||
pending_block_details: RwLock::new(HashMap::new()),
|
||||
@@ -813,18 +810,7 @@ impl BlockChain {
|
||||
}, is_best);
|
||||
|
||||
if is_ancient {
|
||||
let mut best_ancient_block = self.best_ancient_block.write();
|
||||
let ancient_number = best_ancient_block.as_ref().map_or(0, |b| b.number);
|
||||
if self.block_hash(block_number + 1).is_some() {
|
||||
batch.delete(db::COL_EXTRA, b"ancient");
|
||||
*best_ancient_block = None;
|
||||
} else if block_number > ancient_number {
|
||||
batch.put(db::COL_EXTRA, b"ancient", &hash);
|
||||
*best_ancient_block = Some(BestAncientBlock {
|
||||
hash: hash,
|
||||
number: block_number,
|
||||
});
|
||||
}
|
||||
self.set_best_ancient_block(block_number, &hash, batch);
|
||||
}
|
||||
|
||||
false
|
||||
@@ -865,6 +851,84 @@ impl BlockChain {
|
||||
}
|
||||
}
|
||||
|
||||
/// Update the best ancient block to the given hash, after checking that
|
||||
/// it's directly linked to the currently known best ancient block
|
||||
pub fn update_best_ancient_block(&self, hash: &H256) {
|
||||
// Get the block view of the next ancient block (it must
|
||||
// be in DB at this point)
|
||||
let block_view = match self.block(hash) {
|
||||
Some(v) => v,
|
||||
None => return,
|
||||
};
|
||||
|
||||
// So that `best_ancient_block` gets unlocked before calling
|
||||
// `set_best_ancient_block`
|
||||
{
|
||||
// Get the target hash ; if there are no ancient block,
|
||||
// it means that the chain is already fully linked
|
||||
// Release the `best_ancient_block` RwLock
|
||||
let target_hash = {
|
||||
let best_ancient_block = self.best_ancient_block.read();
|
||||
let cur_ancient_block = match *best_ancient_block {
|
||||
Some(ref b) => b,
|
||||
None => return,
|
||||
};
|
||||
|
||||
// Ensure that the new best ancient block is after the current one
|
||||
if block_view.number() <= cur_ancient_block.number {
|
||||
return;
|
||||
}
|
||||
|
||||
cur_ancient_block.hash.clone()
|
||||
};
|
||||
|
||||
let mut block_hash = *hash;
|
||||
let mut is_linked = false;
|
||||
|
||||
loop {
|
||||
if block_hash == target_hash {
|
||||
is_linked = true;
|
||||
break;
|
||||
}
|
||||
|
||||
match self.block_details(&block_hash) {
|
||||
Some(block_details) => {
|
||||
block_hash = block_details.parent;
|
||||
},
|
||||
None => break,
|
||||
}
|
||||
}
|
||||
|
||||
if !is_linked {
|
||||
trace!(target: "blockchain", "The given block {:x} is not linked to the known ancient block {:x}", hash, target_hash);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let mut batch = self.db.key_value().transaction();
|
||||
self.set_best_ancient_block(block_view.number(), hash, &mut batch);
|
||||
self.db.key_value().write(batch).expect("Low level database error.");
|
||||
}
|
||||
|
||||
/// Set the best ancient block with the given value: private method
|
||||
/// `best_ancient_block` must not be locked, otherwise a DeadLock would occur
|
||||
fn set_best_ancient_block(&self, block_number: BlockNumber, block_hash: &H256, batch: &mut DBTransaction) {
|
||||
let mut pending_best_ancient_block = self.pending_best_ancient_block.write();
|
||||
let ancient_number = self.best_ancient_block.read().as_ref().map_or(0, |b| b.number);
|
||||
if self.block_hash(block_number + 1).is_some() {
|
||||
trace!(target: "blockchain", "The two ends of the chain have met.");
|
||||
batch.delete(db::COL_EXTRA, b"ancient");
|
||||
*pending_best_ancient_block = Some(None);
|
||||
} else if block_number > ancient_number {
|
||||
trace!(target: "blockchain", "Updating the best ancient block to {}.", block_number);
|
||||
batch.put(db::COL_EXTRA, b"ancient", &block_hash);
|
||||
*pending_best_ancient_block = Some(Some(BestAncientBlock {
|
||||
hash: *block_hash,
|
||||
number: block_number,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
/// Insert an epoch transition. Provide an epoch number being transitioned to
|
||||
/// and epoch transition object.
|
||||
///
|
||||
@@ -1117,15 +1181,21 @@ impl BlockChain {
|
||||
|
||||
/// Apply pending insertion updates
|
||||
pub fn commit(&self) {
|
||||
let mut pending_best_ancient_block = self.pending_best_ancient_block.write();
|
||||
let mut pending_best_block = self.pending_best_block.write();
|
||||
let mut pending_write_hashes = self.pending_block_hashes.write();
|
||||
let mut pending_block_details = self.pending_block_details.write();
|
||||
let mut pending_write_txs = self.pending_transaction_addresses.write();
|
||||
|
||||
let mut best_block = self.best_block.write();
|
||||
let mut best_ancient_block = self.best_ancient_block.write();
|
||||
let mut write_block_details = self.block_details.write();
|
||||
let mut write_hashes = self.block_hashes.write();
|
||||
let mut write_txs = self.transaction_addresses.write();
|
||||
// update best ancient block
|
||||
if let Some(block_option) = pending_best_ancient_block.take() {
|
||||
*best_ancient_block = block_option;
|
||||
}
|
||||
// update best block
|
||||
if let Some(block) = pending_best_block.take() {
|
||||
*best_block = block;
|
||||
|
||||
@@ -51,7 +51,7 @@ impl Block {
|
||||
|
||||
#[inline]
|
||||
pub fn encoded(&self) -> encoded::Block {
|
||||
encoded::Block::new(encode(self).into_vec())
|
||||
encoded::Block::new(encode(self))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
||||
@@ -311,35 +311,51 @@ impl Impl for Ripemd160 {
|
||||
}
|
||||
}
|
||||
|
||||
// calculate modexp: exponentiation by squaring. the `num` crate has pow, but not modular.
|
||||
fn modexp(mut base: BigUint, mut exp: BigUint, modulus: BigUint) -> BigUint {
|
||||
use num::Integer;
|
||||
// calculate modexp: left-to-right binary exponentiation to keep multiplicands lower
|
||||
fn modexp(mut base: BigUint, exp: Vec<u8>, modulus: BigUint) -> BigUint {
|
||||
const BITS_PER_DIGIT: usize = 8;
|
||||
|
||||
if modulus <= BigUint::one() { // n^m % 0 || n^m % 1
|
||||
// n^m % 0 || n^m % 1
|
||||
if modulus <= BigUint::one() {
|
||||
return BigUint::zero();
|
||||
}
|
||||
|
||||
if exp.is_zero() { // n^0 % m
|
||||
// normalize exponent
|
||||
let mut exp = exp.into_iter().skip_while(|d| *d == 0).peekable();
|
||||
|
||||
// n^0 % m
|
||||
if let None = exp.peek() {
|
||||
return BigUint::one();
|
||||
}
|
||||
|
||||
if base.is_zero() { // 0^n % m, n>0
|
||||
// 0^n % m, n > 0
|
||||
if base.is_zero() {
|
||||
return BigUint::zero();
|
||||
}
|
||||
|
||||
let mut result = BigUint::one();
|
||||
base = base % &modulus;
|
||||
|
||||
// fast path for base divisible by modulus.
|
||||
// Fast path for base divisible by modulus.
|
||||
if base.is_zero() { return BigUint::zero() }
|
||||
while !exp.is_zero() {
|
||||
if exp.is_odd() {
|
||||
result = (result * &base) % &modulus;
|
||||
}
|
||||
|
||||
exp = exp >> 1;
|
||||
base = (base.clone() * base) % &modulus;
|
||||
// Left-to-right binary exponentiation (Handbook of Applied Cryptography - Algorithm 14.79).
|
||||
// http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
|
||||
let mut result = BigUint::one();
|
||||
|
||||
for digit in exp {
|
||||
let mut mask = 1 << (BITS_PER_DIGIT - 1);
|
||||
|
||||
for _ in 0..BITS_PER_DIGIT {
|
||||
result = &result * &result % &modulus;
|
||||
|
||||
if digit & mask > 0 {
|
||||
result = result * &base % &modulus;
|
||||
}
|
||||
|
||||
mask >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
@@ -366,15 +382,19 @@ impl Impl for ModexpImpl {
|
||||
} else {
|
||||
// read the numbers themselves.
|
||||
let mut buf = vec![0; max(mod_len, max(base_len, exp_len))];
|
||||
let mut read_num = |len| {
|
||||
let mut read_num = |reader: &mut io::Chain<&[u8], io::Repeat>, len: usize| {
|
||||
reader.read_exact(&mut buf[..len]).expect("reading from zero-extended memory cannot fail; qed");
|
||||
BigUint::from_bytes_be(&buf[..len])
|
||||
};
|
||||
|
||||
let base = read_num(base_len);
|
||||
let exp = read_num(exp_len);
|
||||
let modulus = read_num(mod_len);
|
||||
modexp(base, exp, modulus)
|
||||
let base = read_num(&mut reader, base_len);
|
||||
|
||||
let mut exp_buf = vec![0; exp_len];
|
||||
reader.read_exact(&mut exp_buf[..exp_len]).expect("reading from zero-extended memory cannot fail; qed");
|
||||
|
||||
let modulus = read_num(&mut reader, mod_len);
|
||||
|
||||
modexp(base, exp_buf, modulus)
|
||||
};
|
||||
|
||||
// write output to given memory, left padded and same length as the modulus.
|
||||
@@ -551,31 +571,31 @@ mod tests {
|
||||
let mut base = BigUint::parse_bytes(b"12345", 10).unwrap();
|
||||
let mut exp = BigUint::zero();
|
||||
let mut modulus = BigUint::parse_bytes(b"789", 10).unwrap();
|
||||
assert_eq!(me(base, exp, modulus), BigUint::one());
|
||||
assert_eq!(me(base, exp.to_bytes_be(), modulus), BigUint::one());
|
||||
|
||||
// 0^n % m == 0
|
||||
base = BigUint::zero();
|
||||
exp = BigUint::parse_bytes(b"12345", 10).unwrap();
|
||||
modulus = BigUint::parse_bytes(b"789", 10).unwrap();
|
||||
assert_eq!(me(base, exp, modulus), BigUint::zero());
|
||||
assert_eq!(me(base, exp.to_bytes_be(), modulus), BigUint::zero());
|
||||
|
||||
// n^m % 1 == 0
|
||||
base = BigUint::parse_bytes(b"12345", 10).unwrap();
|
||||
exp = BigUint::parse_bytes(b"789", 10).unwrap();
|
||||
modulus = BigUint::one();
|
||||
assert_eq!(me(base, exp, modulus), BigUint::zero());
|
||||
assert_eq!(me(base, exp.to_bytes_be(), modulus), BigUint::zero());
|
||||
|
||||
// if n % d == 0, then n^m % d == 0
|
||||
base = BigUint::parse_bytes(b"12345", 10).unwrap();
|
||||
exp = BigUint::parse_bytes(b"789", 10).unwrap();
|
||||
modulus = BigUint::parse_bytes(b"15", 10).unwrap();
|
||||
assert_eq!(me(base, exp, modulus), BigUint::zero());
|
||||
assert_eq!(me(base, exp.to_bytes_be(), modulus), BigUint::zero());
|
||||
|
||||
// others
|
||||
base = BigUint::parse_bytes(b"12345", 10).unwrap();
|
||||
exp = BigUint::parse_bytes(b"789", 10).unwrap();
|
||||
modulus = BigUint::parse_bytes(b"97", 10).unwrap();
|
||||
assert_eq!(me(base, exp, modulus), BigUint::parse_bytes(b"55", 10).unwrap());
|
||||
assert_eq!(me(base, exp.to_bytes_be(), modulus), BigUint::parse_bytes(b"55", 10).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use bytes::Bytes;
|
||||
use ethereum_types::H256;
|
||||
use ethereum_types::{H256, U256};
|
||||
use transaction::UnverifiedTransaction;
|
||||
use blockchain::ImportRoute;
|
||||
use std::time::Duration;
|
||||
@@ -114,19 +114,51 @@ impl ChainRoute {
|
||||
}
|
||||
}
|
||||
|
||||
/// Used by `ChainNotify` `new_blocks()`
|
||||
pub struct NewBlocks {
|
||||
/// Imported blocks
|
||||
pub imported: Vec<H256>,
|
||||
/// Invalid blocks
|
||||
pub invalid: Vec<H256>,
|
||||
/// Route
|
||||
pub route: ChainRoute,
|
||||
/// Sealed
|
||||
pub sealed: Vec<H256>,
|
||||
/// Block bytes.
|
||||
pub proposed: Vec<Bytes>,
|
||||
/// Duration
|
||||
pub duration: Duration,
|
||||
/// Has more blocks to import
|
||||
pub has_more_blocks_to_import: bool,
|
||||
}
|
||||
|
||||
impl NewBlocks {
|
||||
/// Constructor
|
||||
pub fn new (
|
||||
imported: Vec<H256>,
|
||||
invalid: Vec<H256>,
|
||||
route: ChainRoute,
|
||||
sealed: Vec<H256>,
|
||||
proposed: Vec<Bytes>,
|
||||
duration: Duration,
|
||||
has_more_blocks_to_import: bool,
|
||||
) -> NewBlocks {
|
||||
NewBlocks {
|
||||
imported,
|
||||
invalid,
|
||||
route,
|
||||
sealed,
|
||||
proposed,
|
||||
duration,
|
||||
has_more_blocks_to_import,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents what has to be handled by actor listening to chain events
|
||||
pub trait ChainNotify : Send + Sync {
|
||||
/// fires when chain has new blocks.
|
||||
fn new_blocks(
|
||||
&self,
|
||||
_imported: Vec<H256>,
|
||||
_invalid: Vec<H256>,
|
||||
_route: ChainRoute,
|
||||
_sealed: Vec<H256>,
|
||||
// Block bytes.
|
||||
_proposed: Vec<Bytes>,
|
||||
_duration: Duration,
|
||||
) {
|
||||
fn new_blocks( &self, _new_blocks: NewBlocks) {
|
||||
// does nothing by default
|
||||
}
|
||||
|
||||
@@ -141,7 +173,15 @@ pub trait ChainNotify : Send + Sync {
|
||||
}
|
||||
|
||||
/// fires when chain broadcasts a message
|
||||
fn broadcast(&self, _message_type: ChainMessageType) {}
|
||||
fn broadcast(&self, _message_type: ChainMessageType) {
|
||||
// does nothing by default
|
||||
}
|
||||
|
||||
/// fires when new block is about to be imported
|
||||
/// implementations should be light
|
||||
fn block_pre_import(&self, _bytes: &Bytes, _hash: &H256, _difficulty: &U256) {
|
||||
// does nothing by default
|
||||
}
|
||||
|
||||
/// fires when new transactions are received from a peer
|
||||
fn transactions_received(&self,
|
||||
|
||||
@@ -32,7 +32,7 @@ use kvdb::{DBValue, KeyValueDB, DBTransaction};
|
||||
// other
|
||||
use ethereum_types::{H256, Address, U256};
|
||||
use block::{IsBlock, LockedBlock, Drain, ClosedBlock, OpenBlock, enact_verified, SealedBlock};
|
||||
use blockchain::{BlockChain, BlockChainDB, BlockProvider, TreeRoute, ImportRoute, TransactionAddress, ExtrasInsert};
|
||||
use blockchain::{BlockReceipts, BlockChain, BlockChainDB, BlockProvider, TreeRoute, ImportRoute, TransactionAddress, ExtrasInsert};
|
||||
use client::ancient_import::AncientVerifier;
|
||||
use client::{
|
||||
Nonce, Balance, ChainInfo, BlockInfo, CallContract, TransactionInfo,
|
||||
@@ -43,16 +43,16 @@ use client::{
|
||||
};
|
||||
use client::{
|
||||
BlockId, TransactionId, UncleId, TraceId, ClientConfig, BlockChainClient,
|
||||
TraceFilter, CallAnalytics, BlockImportError, Mode,
|
||||
ChainNotify, ChainRoute, PruningInfo, ProvingBlockChainClient, EngineInfo, ChainMessageType,
|
||||
TraceFilter, CallAnalytics, Mode,
|
||||
ChainNotify, NewBlocks, ChainRoute, PruningInfo, ProvingBlockChainClient, EngineInfo, ChainMessageType,
|
||||
IoClient, BadBlocks,
|
||||
};
|
||||
use client::bad_blocks;
|
||||
use encoded;
|
||||
use engines::{EthEngine, EpochTransition, ForkChoice};
|
||||
use error::{
|
||||
ImportErrorKind, BlockImportErrorKind, ExecutionError, CallError, BlockError, ImportResult,
|
||||
QueueError, QueueErrorKind, Error as EthcoreError
|
||||
ImportErrorKind, ExecutionError, CallError, BlockError,
|
||||
QueueError, QueueErrorKind, Error as EthcoreError, EthcoreResult, ErrorKind as EthcoreErrorKind
|
||||
};
|
||||
use vm::{EnvInfo, LastHashes};
|
||||
use evm::Schedule;
|
||||
@@ -66,7 +66,7 @@ use ethcore_miner::pool::VerifiedTransaction;
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use rand::OsRng;
|
||||
use receipt::{Receipt, LocalizedReceipt};
|
||||
use snapshot::{self, io as snapshot_io};
|
||||
use snapshot::{self, io as snapshot_io, SnapshotClient};
|
||||
use spec::Spec;
|
||||
use state_db::StateDB;
|
||||
use state::{self, State};
|
||||
@@ -86,7 +86,7 @@ pub use types::block_status::BlockStatus;
|
||||
pub use blockchain::CacheSize as BlockChainCacheSize;
|
||||
pub use verification::QueueInfo as BlockQueueInfo;
|
||||
|
||||
use_contract!(registry, "Registry", "res/contracts/registrar.json");
|
||||
use_contract!(registry, "res/contracts/registrar.json");
|
||||
|
||||
const MAX_ANCIENT_BLOCKS_QUEUE_SIZE: usize = 4096;
|
||||
// Max number of blocks imported at once.
|
||||
@@ -232,8 +232,6 @@ pub struct Client {
|
||||
/// An action to be done if a mode/spec_name change happens
|
||||
on_user_defaults_change: Mutex<Option<Box<FnMut(Option<Mode>) + 'static + Send>>>,
|
||||
|
||||
/// Link to a registry object useful for looking up names
|
||||
registrar: registry::Registry,
|
||||
registrar_address: Option<Address>,
|
||||
|
||||
/// A closure to call when we want to restart the client
|
||||
@@ -264,14 +262,13 @@ impl Importer {
|
||||
|
||||
/// This is triggered by a message coming from a block queue when the block is ready for insertion
|
||||
pub fn import_verified_blocks(&self, client: &Client) -> usize {
|
||||
|
||||
// Shortcut out if we know we're incapable of syncing the chain.
|
||||
if !client.enabled.load(AtomicOrdering::Relaxed) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let max_blocks_to_import = 4;
|
||||
let (imported_blocks, import_results, invalid_blocks, imported, proposed_blocks, duration, is_empty) = {
|
||||
let max_blocks_to_import = client.config.max_round_blocks_to_import;
|
||||
let (imported_blocks, import_results, invalid_blocks, imported, proposed_blocks, duration, has_more_blocks_to_import) = {
|
||||
let mut imported_blocks = Vec::with_capacity(max_blocks_to_import);
|
||||
let mut invalid_blocks = HashSet::new();
|
||||
let mut proposed_blocks = Vec::with_capacity(max_blocks_to_import);
|
||||
@@ -296,7 +293,6 @@ impl Importer {
|
||||
continue;
|
||||
}
|
||||
|
||||
let raw = block.bytes.clone();
|
||||
match self.check_and_lock_block(block, client) {
|
||||
Ok(closed_block) => {
|
||||
if self.engine.is_proposal(&header) {
|
||||
@@ -314,8 +310,8 @@ impl Importer {
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
self.bad_blocks.report(raw, format!("{:?}", err));
|
||||
invalid_blocks.insert(header.hash());
|
||||
self.bad_blocks.report(bytes, format!("{:?}", err));
|
||||
invalid_blocks.insert(hash);
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -326,26 +322,29 @@ impl Importer {
|
||||
if !invalid_blocks.is_empty() {
|
||||
self.block_queue.mark_as_bad(&invalid_blocks);
|
||||
}
|
||||
let is_empty = self.block_queue.mark_as_good(&imported_blocks);
|
||||
(imported_blocks, import_results, invalid_blocks, imported, proposed_blocks, start.elapsed(), is_empty)
|
||||
let has_more_blocks_to_import = !self.block_queue.mark_as_good(&imported_blocks);
|
||||
(imported_blocks, import_results, invalid_blocks, imported, proposed_blocks, start.elapsed(), has_more_blocks_to_import)
|
||||
};
|
||||
|
||||
{
|
||||
if !imported_blocks.is_empty() && is_empty {
|
||||
if !imported_blocks.is_empty() {
|
||||
let route = ChainRoute::from(import_results.as_ref());
|
||||
|
||||
if is_empty {
|
||||
if !has_more_blocks_to_import {
|
||||
self.miner.chain_new_blocks(client, &imported_blocks, &invalid_blocks, route.enacted(), route.retracted(), false);
|
||||
}
|
||||
|
||||
client.notify(|notify| {
|
||||
notify.new_blocks(
|
||||
NewBlocks::new(
|
||||
imported_blocks.clone(),
|
||||
invalid_blocks.clone(),
|
||||
route.clone(),
|
||||
Vec::new(),
|
||||
proposed_blocks.clone(),
|
||||
duration,
|
||||
has_more_blocks_to_import,
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -356,7 +355,7 @@ impl Importer {
|
||||
imported
|
||||
}
|
||||
|
||||
fn check_and_lock_block(&self, block: PreverifiedBlock, client: &Client) -> Result<LockedBlock, ()> {
|
||||
fn check_and_lock_block(&self, block: PreverifiedBlock, client: &Client) -> EthcoreResult<LockedBlock> {
|
||||
let engine = &*self.engine;
|
||||
let header = block.header.clone();
|
||||
|
||||
@@ -364,7 +363,7 @@ impl Importer {
|
||||
let best_block_number = client.chain.read().best_block_number();
|
||||
if client.pruning_info().earliest_state > header.number() {
|
||||
warn!(target: "client", "Block import failed for #{} ({})\nBlock is ancient (current best block: #{}).", header.number(), header.hash(), best_block_number);
|
||||
return Err(());
|
||||
bail!("Block is ancient");
|
||||
}
|
||||
|
||||
// Check if parent is in chain
|
||||
@@ -372,7 +371,7 @@ impl Importer {
|
||||
Some(h) => h,
|
||||
None => {
|
||||
warn!(target: "client", "Block import failed for #{} ({}): Parent not found ({}) ", header.number(), header.hash(), header.parent_hash());
|
||||
return Err(());
|
||||
bail!("Parent not found");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -391,13 +390,13 @@ impl Importer {
|
||||
|
||||
if let Err(e) = verify_family_result {
|
||||
warn!(target: "client", "Stage 3 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e);
|
||||
return Err(());
|
||||
bail!(e);
|
||||
};
|
||||
|
||||
let verify_external_result = self.verifier.verify_block_external(&header, engine);
|
||||
if let Err(e) = verify_external_result {
|
||||
warn!(target: "client", "Stage 4 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e);
|
||||
return Err(());
|
||||
bail!(e);
|
||||
};
|
||||
|
||||
// Enact Verified Block
|
||||
@@ -417,9 +416,13 @@ impl Importer {
|
||||
&mut chain.ancestry_with_metadata_iter(*header.parent_hash()),
|
||||
);
|
||||
|
||||
let mut locked_block = enact_result.map_err(|e| {
|
||||
warn!(target: "client", "Block import failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e);
|
||||
})?;
|
||||
let mut locked_block = match enact_result {
|
||||
Ok(b) => b,
|
||||
Err(e) => {
|
||||
warn!(target: "client", "Block import failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e);
|
||||
bail!(e);
|
||||
}
|
||||
};
|
||||
|
||||
// Strip receipts for blocks before validate_receipts_transition,
|
||||
// if the expected receipts root header does not match.
|
||||
@@ -433,7 +436,7 @@ impl Importer {
|
||||
// Final Verification
|
||||
if let Err(e) = self.verifier.verify_block_final(&header, locked_block.block().header()) {
|
||||
warn!(target: "client", "Stage 5 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e);
|
||||
return Err(());
|
||||
bail!(e);
|
||||
}
|
||||
|
||||
Ok(locked_block)
|
||||
@@ -443,7 +446,7 @@ impl Importer {
|
||||
///
|
||||
/// The block is guaranteed to be the next best blocks in the
|
||||
/// first block sequence. Does no sealing or transaction validation.
|
||||
fn import_old_block(&self, unverified: Unverified, receipts_bytes: &[u8], db: &KeyValueDB, chain: &BlockChain) -> Result<(), ::error::Error> {
|
||||
fn import_old_block(&self, unverified: Unverified, receipts_bytes: &[u8], db: &KeyValueDB, chain: &BlockChain) -> EthcoreResult<()> {
|
||||
let receipts = ::rlp::decode_list(receipts_bytes);
|
||||
let _import_lock = self.import_lock.lock();
|
||||
|
||||
@@ -473,7 +476,7 @@ impl Importer {
|
||||
let number = header.number();
|
||||
let parent = header.parent_hash();
|
||||
let chain = client.chain.read();
|
||||
let is_finalized = false;
|
||||
let mut is_finalized = false;
|
||||
|
||||
// Commit results
|
||||
let block = block.drain();
|
||||
@@ -481,7 +484,7 @@ impl Importer {
|
||||
|
||||
let mut batch = DBTransaction::new();
|
||||
|
||||
let ancestry_actions = self.engine.ancestry_actions(&block, &mut chain.ancestry_with_metadata_iter(*parent));
|
||||
let ancestry_actions = self.engine.ancestry_actions(&header, &mut chain.ancestry_with_metadata_iter(*parent));
|
||||
|
||||
let receipts = block.receipts;
|
||||
let traces = block.traces.drain();
|
||||
@@ -535,10 +538,18 @@ impl Importer {
|
||||
|
||||
state.journal_under(&mut batch, number, hash).expect("DB commit failed");
|
||||
|
||||
for ancestry_action in ancestry_actions {
|
||||
let AncestryAction::MarkFinalized(ancestry) = ancestry_action;
|
||||
chain.mark_finalized(&mut batch, ancestry).expect("Engine's ancestry action must be known blocks; qed");
|
||||
}
|
||||
let finalized: Vec<_> = ancestry_actions.into_iter().map(|ancestry_action| {
|
||||
let AncestryAction::MarkFinalized(a) = ancestry_action;
|
||||
|
||||
if a != header.hash() {
|
||||
chain.mark_finalized(&mut batch, a).expect("Engine's ancestry action must be known blocks; qed");
|
||||
} else {
|
||||
// we're finalizing the current block
|
||||
is_finalized = true;
|
||||
}
|
||||
|
||||
a
|
||||
}).collect();
|
||||
|
||||
let route = chain.insert_block(&mut batch, block_data, receipts.clone(), ExtrasInsert {
|
||||
fork_choice: fork_choice,
|
||||
@@ -559,7 +570,7 @@ impl Importer {
|
||||
client.db.read().key_value().write_buffered(batch);
|
||||
chain.commit();
|
||||
|
||||
self.check_epoch_end(&header, &chain, client);
|
||||
self.check_epoch_end(&header, &finalized, &chain, client);
|
||||
|
||||
client.update_last_hashes(&parent, hash);
|
||||
|
||||
@@ -666,9 +677,10 @@ impl Importer {
|
||||
}
|
||||
|
||||
// check for ending of epoch and write transition if it occurs.
|
||||
fn check_epoch_end<'a>(&self, header: &'a Header, chain: &BlockChain, client: &Client) {
|
||||
fn check_epoch_end<'a>(&self, header: &'a Header, finalized: &'a [H256], chain: &BlockChain, client: &Client) {
|
||||
let is_epoch_end = self.engine.is_epoch_end(
|
||||
header,
|
||||
finalized,
|
||||
&(|hash| client.block_header_decoded(BlockId::Hash(hash))),
|
||||
&(|hash| chain.get_pending_transition(hash)), // TODO: limit to current epoch.
|
||||
);
|
||||
@@ -776,7 +788,6 @@ impl Client {
|
||||
factories: factories,
|
||||
history: history,
|
||||
on_user_defaults_change: Mutex::new(None),
|
||||
registrar: registry::Registry::default(),
|
||||
registrar_address,
|
||||
exit_handler: Mutex::new(None),
|
||||
importer,
|
||||
@@ -873,7 +884,7 @@ impl Client {
|
||||
/// Flush the block import queue.
|
||||
pub fn flush_queue(&self) {
|
||||
self.importer.block_queue.flush();
|
||||
while !self.importer.block_queue.queue_info().is_empty() {
|
||||
while !self.importer.block_queue.is_empty() {
|
||||
self.import_verified_blocks();
|
||||
}
|
||||
}
|
||||
@@ -997,6 +1008,16 @@ impl Client {
|
||||
self.importer.miner.clone()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn state_db(&self) -> ::parking_lot::RwLockReadGuard<StateDB> {
|
||||
self.state_db.read()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn chain(&self) -> Arc<BlockChain> {
|
||||
self.chain.read().clone()
|
||||
}
|
||||
|
||||
/// Replace io channel. Useful for testing.
|
||||
pub fn set_io_channel(&self, io_channel: IoChannel<ClientIoMessage>) {
|
||||
*self.io_channel.write() = io_channel;
|
||||
@@ -1153,7 +1174,8 @@ impl Client {
|
||||
},
|
||||
};
|
||||
|
||||
snapshot::take_snapshot(&*self.engine, &self.chain.read(), start_hash, db.as_hashdb(), writer, p)?;
|
||||
let processing_threads = self.config.snapshot.processing_threads;
|
||||
snapshot::take_snapshot(&*self.engine, &self.chain.read(), start_hash, db.as_hashdb(), writer, p, processing_threads)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1365,17 +1387,17 @@ impl BlockChainTrait for Client {}
|
||||
|
||||
impl RegistryInfo for Client {
|
||||
fn registry_address(&self, name: String, block: BlockId) -> Option<Address> {
|
||||
use ethabi::FunctionOutputDecoder;
|
||||
|
||||
let address = self.registrar_address?;
|
||||
|
||||
self.registrar.functions()
|
||||
.get_address()
|
||||
.call(keccak(name.as_bytes()), "A", &|data| self.call_contract(block, address, data))
|
||||
.ok()
|
||||
.and_then(|a| if a.is_zero() {
|
||||
None
|
||||
} else {
|
||||
Some(a)
|
||||
})
|
||||
let (data, decoder) = registry::functions::get_address::call(keccak(name.as_bytes()), "A");
|
||||
let value = decoder.decode(&self.call_contract(block, address, data).ok()?).ok()?;
|
||||
if value.is_zero() {
|
||||
None
|
||||
} else {
|
||||
Some(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1394,25 +1416,37 @@ impl CallContract for Client {
|
||||
}
|
||||
|
||||
impl ImportBlock for Client {
|
||||
fn import_block(&self, unverified: Unverified) -> Result<H256, BlockImportError> {
|
||||
fn import_block(&self, unverified: Unverified) -> EthcoreResult<H256> {
|
||||
if self.chain.read().is_known(&unverified.hash()) {
|
||||
bail!(BlockImportErrorKind::Import(ImportErrorKind::AlreadyInChain));
|
||||
bail!(EthcoreErrorKind::Import(ImportErrorKind::AlreadyInChain));
|
||||
}
|
||||
|
||||
let status = self.block_status(BlockId::Hash(unverified.parent_hash()));
|
||||
if status == BlockStatus::Unknown {
|
||||
bail!(BlockImportErrorKind::Block(BlockError::UnknownParent(unverified.parent_hash())));
|
||||
bail!(EthcoreErrorKind::Block(BlockError::UnknownParent(unverified.parent_hash())));
|
||||
}
|
||||
|
||||
let raw = unverified.bytes.clone();
|
||||
match self.importer.block_queue.import(unverified).map_err(Into::into) {
|
||||
Ok(res) => Ok(res),
|
||||
// we only care about block errors (not import errors)
|
||||
Err(BlockImportError(BlockImportErrorKind::Block(err), _))=> {
|
||||
self.importer.bad_blocks.report(raw, format!("{:?}", err));
|
||||
bail!(BlockImportErrorKind::Block(err))
|
||||
let raw = if self.importer.block_queue.is_empty() {
|
||||
Some((
|
||||
unverified.bytes.clone(),
|
||||
unverified.header.hash(),
|
||||
*unverified.header.difficulty(),
|
||||
))
|
||||
} else { None };
|
||||
|
||||
match self.importer.block_queue.import(unverified) {
|
||||
Ok(hash) => {
|
||||
if let Some((raw, hash, difficulty)) = raw {
|
||||
self.notify(move |n| n.block_pre_import(&raw, &hash, &difficulty));
|
||||
}
|
||||
Ok(hash)
|
||||
},
|
||||
Err(e) => Err(e),
|
||||
// we only care about block errors (not import errors)
|
||||
Err((block, EthcoreError(EthcoreErrorKind::Block(err), _))) => {
|
||||
self.importer.bad_blocks.report(block.bytes, format!("{:?}", err));
|
||||
bail!(EthcoreErrorKind::Block(err))
|
||||
},
|
||||
Err((_, e)) => Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1491,7 +1525,7 @@ impl Call for Client {
|
||||
let sender = t.sender();
|
||||
let options = || TransactOptions::with_tracing().dont_check_nonce();
|
||||
|
||||
let cond = |gas| {
|
||||
let exec = |gas| {
|
||||
let mut tx = t.as_unsigned().clone();
|
||||
tx.gas = gas;
|
||||
let tx = tx.fake_sign(sender);
|
||||
@@ -1499,22 +1533,28 @@ impl Call for Client {
|
||||
let mut clone = state.clone();
|
||||
let machine = self.engine.machine();
|
||||
let schedule = machine.schedule(env_info.number);
|
||||
Ok(Executive::new(&mut clone, &env_info, &machine, &schedule)
|
||||
Executive::new(&mut clone, &env_info, &machine, &schedule)
|
||||
.transact_virtual(&tx, options())
|
||||
.ok()
|
||||
.map(|r| r.exception.is_none())
|
||||
.unwrap_or(false))
|
||||
};
|
||||
|
||||
if !cond(upper)? {
|
||||
let cond = |gas| exec(gas).unwrap_or(false);
|
||||
|
||||
if !cond(upper) {
|
||||
upper = max_upper;
|
||||
if !cond(upper)? {
|
||||
trace!(target: "estimate_gas", "estimate_gas failed with {}", upper);
|
||||
let err = ExecutionError::Internal(format!("Requires higher than upper limit of {}", upper));
|
||||
return Err(err.into())
|
||||
match exec(upper) {
|
||||
Some(false) => return Err(CallError::Exceptional),
|
||||
None => {
|
||||
trace!(target: "estimate_gas", "estimate_gas failed with {}", upper);
|
||||
let err = ExecutionError::Internal(format!("Requires higher than upper limit of {}", upper));
|
||||
return Err(err.into())
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
let lower = t.gas_required(&self.engine.schedule(env_info.number)).into();
|
||||
if cond(lower)? {
|
||||
if cond(lower) {
|
||||
trace!(target: "estimate_gas", "estimate_gas succeeded with {}", lower);
|
||||
return Ok(lower)
|
||||
}
|
||||
@@ -1523,12 +1563,12 @@ impl Call for Client {
|
||||
/// Returns the lowest value between `lower` and `upper` for which `cond` returns true.
|
||||
/// We assert: `cond(lower) = false`, `cond(upper) = true`
|
||||
fn binary_chop<F, E>(mut lower: U256, mut upper: U256, mut cond: F) -> Result<U256, E>
|
||||
where F: FnMut(U256) -> Result<bool, E>
|
||||
where F: FnMut(U256) -> bool
|
||||
{
|
||||
while upper - lower > 1.into() {
|
||||
let mid = (lower + upper) / 2;
|
||||
trace!(target: "estimate_gas", "{} .. {} .. {}", lower, mid, upper);
|
||||
let c = cond(mid)?;
|
||||
let c = cond(mid);
|
||||
match c {
|
||||
true => upper = mid,
|
||||
false => lower = mid,
|
||||
@@ -1785,26 +1825,49 @@ impl BlockChainClient for Client {
|
||||
}
|
||||
|
||||
fn transaction_receipt(&self, id: TransactionId) -> Option<LocalizedReceipt> {
|
||||
// NOTE Don't use block_receipts here for performance reasons
|
||||
let address = self.transaction_address(id)?;
|
||||
let hash = address.block_hash;
|
||||
let chain = self.chain.read();
|
||||
self.transaction_address(id)
|
||||
.and_then(|address| chain.block_number(&address.block_hash).and_then(|block_number| {
|
||||
let transaction = chain.block_body(&address.block_hash)
|
||||
.and_then(|body| body.view().localized_transaction_at(&address.block_hash, block_number, address.index));
|
||||
let number = chain.block_number(&hash)?;
|
||||
let body = chain.block_body(&hash)?;
|
||||
let mut receipts = chain.block_receipts(&hash)?.receipts;
|
||||
receipts.truncate(address.index + 1);
|
||||
|
||||
let previous_receipts = (0..address.index + 1)
|
||||
.map(|index| {
|
||||
let mut address = address.clone();
|
||||
address.index = index;
|
||||
chain.transaction_receipt(&address)
|
||||
})
|
||||
.collect();
|
||||
match (transaction, previous_receipts) {
|
||||
(Some(transaction), Some(previous_receipts)) => {
|
||||
Some(transaction_receipt(self.engine().machine(), transaction, previous_receipts))
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}))
|
||||
let transaction = body.view().localized_transaction_at(&hash, number, address.index)?;
|
||||
let receipt = receipts.pop()?;
|
||||
let gas_used = receipts.last().map_or_else(|| 0.into(), |r| r.gas_used);
|
||||
let no_of_logs = receipts.into_iter().map(|receipt| receipt.logs.len()).sum::<usize>();
|
||||
|
||||
let receipt = transaction_receipt(self.engine().machine(), transaction, receipt, gas_used, no_of_logs);
|
||||
Some(receipt)
|
||||
}
|
||||
|
||||
fn localized_block_receipts(&self, id: BlockId) -> Option<Vec<LocalizedReceipt>> {
|
||||
let hash = self.block_hash(id)?;
|
||||
|
||||
let chain = self.chain.read();
|
||||
let receipts = chain.block_receipts(&hash)?;
|
||||
let number = chain.block_number(&hash)?;
|
||||
let body = chain.block_body(&hash)?;
|
||||
let engine = self.engine.clone();
|
||||
|
||||
let mut gas_used = 0.into();
|
||||
let mut no_of_logs = 0;
|
||||
|
||||
Some(body
|
||||
.view()
|
||||
.localized_transactions(&hash, number)
|
||||
.into_iter()
|
||||
.zip(receipts.receipts)
|
||||
.map(move |(transaction, receipt)| {
|
||||
let result = transaction_receipt(engine.machine(), transaction, receipt, gas_used, no_of_logs);
|
||||
gas_used = result.cumulative_gas_used;
|
||||
no_of_logs += result.logs.len();
|
||||
result
|
||||
})
|
||||
.collect()
|
||||
)
|
||||
}
|
||||
|
||||
fn tree_route(&self, from: &H256, to: &H256) -> Option<TreeRoute> {
|
||||
@@ -1823,14 +1886,18 @@ impl BlockChainClient for Client {
|
||||
self.state_db.read().journal_db().state(hash)
|
||||
}
|
||||
|
||||
fn block_receipts(&self, hash: &H256) -> Option<Bytes> {
|
||||
self.chain.read().block_receipts(hash).map(|receipts| ::rlp::encode(&receipts).into_vec())
|
||||
fn block_receipts(&self, hash: &H256) -> Option<BlockReceipts> {
|
||||
self.chain.read().block_receipts(hash)
|
||||
}
|
||||
|
||||
fn queue_info(&self) -> BlockQueueInfo {
|
||||
self.importer.block_queue.queue_info()
|
||||
}
|
||||
|
||||
fn is_queue_empty(&self) -> bool {
|
||||
self.importer.block_queue.is_empty()
|
||||
}
|
||||
|
||||
fn clear_queue(&self) {
|
||||
self.importer.block_queue.clear();
|
||||
}
|
||||
@@ -2087,24 +2154,21 @@ impl IoClient for Client {
|
||||
});
|
||||
}
|
||||
|
||||
fn queue_ancient_block(&self, unverified: Unverified, receipts_bytes: Bytes) -> Result<H256, BlockImportError> {
|
||||
fn queue_ancient_block(&self, unverified: Unverified, receipts_bytes: Bytes) -> EthcoreResult<H256> {
|
||||
trace_time!("queue_ancient_block");
|
||||
|
||||
let hash = unverified.hash();
|
||||
{
|
||||
// check block order
|
||||
if self.chain.read().is_known(&hash) {
|
||||
bail!(BlockImportErrorKind::Import(ImportErrorKind::AlreadyInChain));
|
||||
bail!(EthcoreErrorKind::Import(ImportErrorKind::AlreadyInChain));
|
||||
}
|
||||
let parent_hash = unverified.parent_hash();
|
||||
// NOTE To prevent race condition with import, make sure to check queued blocks first
|
||||
// (and attempt to acquire lock)
|
||||
let is_parent_pending = self.queued_ancient_blocks.read().0.contains(&parent_hash);
|
||||
if !is_parent_pending {
|
||||
let status = self.block_status(BlockId::Hash(parent_hash));
|
||||
if status == BlockStatus::Unknown {
|
||||
bail!(BlockImportErrorKind::Block(BlockError::UnknownParent(parent_hash)));
|
||||
}
|
||||
if !is_parent_pending && !self.chain.read().is_known(&parent_hash) {
|
||||
bail!(EthcoreErrorKind::Block(BlockError::UnknownParent(parent_hash)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2134,6 +2198,10 @@ impl IoClient for Client {
|
||||
);
|
||||
if let Err(e) = result {
|
||||
error!(target: "client", "Error importing ancient block: {}", e);
|
||||
|
||||
let mut queued = queued.write();
|
||||
queued.0.clear();
|
||||
queued.1.clear();
|
||||
}
|
||||
// remove from pending
|
||||
queued.write().0.remove(&hash);
|
||||
@@ -2239,27 +2307,38 @@ impl ScheduleInfo for Client {
|
||||
}
|
||||
|
||||
impl ImportSealedBlock for Client {
|
||||
fn import_sealed_block(&self, block: SealedBlock) -> ImportResult {
|
||||
let h = block.header().hash();
|
||||
fn import_sealed_block(&self, block: SealedBlock) -> EthcoreResult<H256> {
|
||||
let start = Instant::now();
|
||||
let raw = block.rlp_bytes();
|
||||
let header = block.header().clone();
|
||||
let hash = header.hash();
|
||||
self.notify(|n| n.block_pre_import(&raw, &hash, header.difficulty()));
|
||||
|
||||
let route = {
|
||||
// Do a super duper basic verification to detect potential bugs
|
||||
if let Err(e) = self.engine.verify_block_basic(&header) {
|
||||
self.importer.bad_blocks.report(
|
||||
block.rlp_bytes(),
|
||||
format!("Detected an issue with locally sealed block: {}", e),
|
||||
);
|
||||
return Err(e.into());
|
||||
}
|
||||
|
||||
// scope for self.import_lock
|
||||
let _import_lock = self.importer.import_lock.lock();
|
||||
trace_time!("import_sealed_block");
|
||||
|
||||
let number = block.header().number();
|
||||
let block_data = block.rlp_bytes();
|
||||
let header = block.header().clone();
|
||||
|
||||
let route = self.importer.commit_block(block, &header, encoded::Block::new(block_data), self);
|
||||
trace!(target: "client", "Imported sealed block #{} ({})", number, h);
|
||||
trace!(target: "client", "Imported sealed block #{} ({})", header.number(), hash);
|
||||
self.state_db.write().sync_cache(&route.enacted, &route.retracted, false);
|
||||
route
|
||||
};
|
||||
let route = ChainRoute::from([route].as_ref());
|
||||
self.importer.miner.chain_new_blocks(
|
||||
self,
|
||||
&[h.clone()],
|
||||
&[hash],
|
||||
&[],
|
||||
route.enacted(),
|
||||
route.retracted(),
|
||||
@@ -2267,16 +2346,19 @@ impl ImportSealedBlock for Client {
|
||||
);
|
||||
self.notify(|notify| {
|
||||
notify.new_blocks(
|
||||
vec![h.clone()],
|
||||
vec![],
|
||||
route.clone(),
|
||||
vec![h.clone()],
|
||||
vec![],
|
||||
start.elapsed(),
|
||||
NewBlocks::new(
|
||||
vec![hash],
|
||||
vec![],
|
||||
route.clone(),
|
||||
vec![hash],
|
||||
vec![],
|
||||
start.elapsed(),
|
||||
false
|
||||
)
|
||||
);
|
||||
});
|
||||
self.db.read().key_value().flush().expect("DB flush failed.");
|
||||
Ok(h)
|
||||
Ok(hash)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2285,12 +2367,15 @@ impl BroadcastProposalBlock for Client {
|
||||
const DURATION_ZERO: Duration = Duration::from_millis(0);
|
||||
self.notify(|notify| {
|
||||
notify.new_blocks(
|
||||
vec![],
|
||||
vec![],
|
||||
ChainRoute::default(),
|
||||
vec![],
|
||||
vec![block.rlp_bytes()],
|
||||
DURATION_ZERO,
|
||||
NewBlocks::new(
|
||||
vec![],
|
||||
vec![],
|
||||
ChainRoute::default(),
|
||||
vec![],
|
||||
vec![block.rlp_bytes()],
|
||||
DURATION_ZERO,
|
||||
false
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -2352,14 +2437,13 @@ impl ProvingBlockChainClient for Client {
|
||||
env_info.gas_limit = transaction.gas.clone();
|
||||
let mut jdb = self.state_db.read().journal_db().boxed_clone();
|
||||
|
||||
state::prove_transaction(
|
||||
state::prove_transaction_virtual(
|
||||
jdb.as_hashdb_mut(),
|
||||
header.state_root().clone(),
|
||||
&transaction,
|
||||
self.engine.machine(),
|
||||
&env_info,
|
||||
self.factories.clone(),
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2370,6 +2454,8 @@ impl ProvingBlockChainClient for Client {
|
||||
}
|
||||
}
|
||||
|
||||
impl SnapshotClient for Client {}
|
||||
|
||||
impl Drop for Client {
|
||||
fn drop(&mut self) {
|
||||
self.engine.stop();
|
||||
@@ -2378,16 +2464,14 @@ impl Drop for Client {
|
||||
|
||||
/// Returns `LocalizedReceipt` given `LocalizedTransaction`
|
||||
/// and a vector of receipts from given block up to transaction index.
|
||||
fn transaction_receipt(machine: &::machine::EthereumMachine, mut tx: LocalizedTransaction, mut receipts: Vec<Receipt>) -> LocalizedReceipt {
|
||||
assert_eq!(receipts.len(), tx.transaction_index + 1, "All previous receipts are provided.");
|
||||
|
||||
fn transaction_receipt(
|
||||
machine: &::machine::EthereumMachine,
|
||||
mut tx: LocalizedTransaction,
|
||||
receipt: Receipt,
|
||||
prior_gas_used: U256,
|
||||
prior_no_of_logs: usize,
|
||||
) -> LocalizedReceipt {
|
||||
let sender = tx.sender();
|
||||
let receipt = receipts.pop().expect("Current receipt is provided; qed");
|
||||
let prior_gas_used = match tx.transaction_index {
|
||||
0 => 0.into(),
|
||||
i => receipts.get(i - 1).expect("All previous receipts are provided; qed").gas_used,
|
||||
};
|
||||
let no_of_logs = receipts.into_iter().map(|receipt| receipt.logs.len()).sum::<usize>();
|
||||
let transaction_hash = tx.hash();
|
||||
let block_hash = tx.block_hash;
|
||||
let block_number = tx.block_number;
|
||||
@@ -2416,7 +2500,7 @@ fn transaction_receipt(machine: &::machine::EthereumMachine, mut tx: LocalizedTr
|
||||
transaction_hash: transaction_hash,
|
||||
transaction_index: transaction_index,
|
||||
transaction_log_index: i,
|
||||
log_index: no_of_logs + i,
|
||||
log_index: prior_no_of_logs + i,
|
||||
}).collect(),
|
||||
log_bloom: receipt.log_bloom,
|
||||
outcome: receipt.outcome,
|
||||
@@ -2464,6 +2548,33 @@ mod tests {
|
||||
assert!(client.tree_route(&genesis, &new_hash).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_return_block_receipts() {
|
||||
use client::{BlockChainClient, BlockId, TransactionId};
|
||||
use test_helpers::{generate_dummy_client_with_data};
|
||||
|
||||
let client = generate_dummy_client_with_data(2, 2, &[1.into(), 1.into()]);
|
||||
let receipts = client.localized_block_receipts(BlockId::Latest).unwrap();
|
||||
|
||||
assert_eq!(receipts.len(), 2);
|
||||
assert_eq!(receipts[0].transaction_index, 0);
|
||||
assert_eq!(receipts[0].block_number, 2);
|
||||
assert_eq!(receipts[0].cumulative_gas_used, 53_000.into());
|
||||
assert_eq!(receipts[0].gas_used, 53_000.into());
|
||||
|
||||
assert_eq!(receipts[1].transaction_index, 1);
|
||||
assert_eq!(receipts[1].block_number, 2);
|
||||
assert_eq!(receipts[1].cumulative_gas_used, 106_000.into());
|
||||
assert_eq!(receipts[1].gas_used, 53_000.into());
|
||||
|
||||
|
||||
let receipt = client.transaction_receipt(TransactionId::Hash(receipts[0].transaction_hash));
|
||||
assert_eq!(receipt, Some(receipts[0].clone()));
|
||||
|
||||
let receipt = client.transaction_receipt(TransactionId::Hash(receipts[1].transaction_hash));
|
||||
assert_eq!(receipt, Some(receipts[1].clone()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_return_correct_log_index() {
|
||||
use hash::keccak;
|
||||
@@ -2507,20 +2618,15 @@ mod tests {
|
||||
topics: vec![],
|
||||
data: vec![],
|
||||
}];
|
||||
let receipts = vec![Receipt {
|
||||
outcome: TransactionOutcome::StateRoot(state_root),
|
||||
gas_used: 5.into(),
|
||||
log_bloom: Default::default(),
|
||||
logs: vec![logs[0].clone()],
|
||||
}, Receipt {
|
||||
let receipt = Receipt {
|
||||
outcome: TransactionOutcome::StateRoot(state_root),
|
||||
gas_used: gas_used,
|
||||
log_bloom: Default::default(),
|
||||
logs: logs.clone(),
|
||||
}];
|
||||
};
|
||||
|
||||
// when
|
||||
let receipt = transaction_receipt(&machine, transaction, receipts);
|
||||
let receipt = transaction_receipt(&machine, transaction, receipt, 5.into(), 1);
|
||||
|
||||
// then
|
||||
assert_eq!(receipt, LocalizedReceipt {
|
||||
|
||||
@@ -19,6 +19,7 @@ use std::fmt::{Display, Formatter, Error as FmtError};
|
||||
|
||||
use verification::{VerifierType, QueueConfig};
|
||||
use journaldb;
|
||||
use snapshot::SnapshotConfiguration;
|
||||
|
||||
pub use std::time::Duration;
|
||||
pub use blockchain::Config as BlockChainConfig;
|
||||
@@ -120,6 +121,10 @@ pub struct ClientConfig {
|
||||
pub check_seal: bool,
|
||||
/// Maximal number of transactions queued for verification in a separate thread.
|
||||
pub transaction_verification_queue_size: usize,
|
||||
/// Maximal number of blocks to import at each round.
|
||||
pub max_round_blocks_to_import: usize,
|
||||
/// Snapshot configuration
|
||||
pub snapshot: SnapshotConfiguration,
|
||||
}
|
||||
|
||||
impl Default for ClientConfig {
|
||||
@@ -144,6 +149,8 @@ impl Default for ClientConfig {
|
||||
history_mem: 32 * mb,
|
||||
check_seal: true,
|
||||
transaction_verification_queue_size: 8192,
|
||||
max_round_blocks_to_import: 12,
|
||||
snapshot: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,9 +86,10 @@ impl<'a> EvmTestClient<'a> {
|
||||
ForkSpec::EIP150 => Some(ethereum::new_eip150_test()),
|
||||
ForkSpec::EIP158 => Some(ethereum::new_eip161_test()),
|
||||
ForkSpec::Byzantium => Some(ethereum::new_byzantium_test()),
|
||||
ForkSpec::Constantinople => Some(ethereum::new_constantinople_test()),
|
||||
ForkSpec::ConstantinopleFix => Some(ethereum::new_constantinople_fix_test()),
|
||||
ForkSpec::EIP158ToByzantiumAt5 => Some(ethereum::new_transition_test()),
|
||||
ForkSpec::FrontierToHomesteadAt5 | ForkSpec::HomesteadToDaoAt5 | ForkSpec::HomesteadToEIP150At5 => None,
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,6 +183,19 @@ impl<'a> EvmTestClient<'a> {
|
||||
gas_used: 0.into(),
|
||||
gas_limit: *genesis.gas_limit(),
|
||||
};
|
||||
self.call_envinfo(params, tracer, vm_tracer, info)
|
||||
}
|
||||
|
||||
/// Execute the VM given envinfo, ActionParams and tracer.
|
||||
/// Returns amount of gas left and the output.
|
||||
pub fn call_envinfo<T: trace::Tracer, V: trace::VMTracer>(
|
||||
&mut self,
|
||||
params: ActionParams,
|
||||
tracer: &mut T,
|
||||
vm_tracer: &mut V,
|
||||
info: client::EnvInfo,
|
||||
) -> Result<FinalizationResult, EvmTestError>
|
||||
{
|
||||
let mut substate = state::Substate::new();
|
||||
let machine = self.spec.engine.machine();
|
||||
let schedule = machine.schedule(info.number);
|
||||
|
||||
@@ -34,7 +34,7 @@ pub use self::evm_test_client::{EvmTestClient, EvmTestError, TransactResult};
|
||||
pub use self::io_message::ClientIoMessage;
|
||||
#[cfg(any(test, feature = "test-helpers"))]
|
||||
pub use self::test_client::{TestBlockChainClient, EachBlockWith};
|
||||
pub use self::chain_notify::{ChainNotify, ChainRoute, ChainRouteType, ChainMessageType};
|
||||
pub use self::chain_notify::{ChainNotify, NewBlocks, ChainRoute, ChainRouteType, ChainMessageType};
|
||||
pub use self::traits::{
|
||||
Nonce, Balance, ChainInfo, BlockInfo, ReopenBlock, PrepareOpenBlock, CallContract, TransactionInfo, RegistryInfo, ScheduleInfo, ImportSealedBlock, BroadcastProposalBlock, ImportBlock,
|
||||
StateOrBlock, StateClient, Call, EngineInfo, AccountData, BlockChain, BlockProducer, SealedBlockImporter, BadBlocks,
|
||||
@@ -50,7 +50,7 @@ pub use types::call_analytics::CallAnalytics;
|
||||
pub use executive::{Executed, Executive, TransactOptions};
|
||||
pub use vm::{LastHashes, EnvInfo};
|
||||
|
||||
pub use error::{BlockImportError, BlockImportErrorKind, TransactionImportError};
|
||||
pub use error::TransactionImportError;
|
||||
pub use verification::VerifierType;
|
||||
|
||||
mod traits;
|
||||
|
||||
@@ -37,7 +37,7 @@ use blockchain::{TreeRoute, BlockReceipts};
|
||||
use client::{
|
||||
Nonce, Balance, ChainInfo, BlockInfo, ReopenBlock, CallContract, TransactionInfo, RegistryInfo,
|
||||
PrepareOpenBlock, BlockChainClient, BlockChainInfo, BlockStatus, BlockId, Mode,
|
||||
TransactionId, UncleId, TraceId, TraceFilter, LastHashes, CallAnalytics, BlockImportError,
|
||||
TransactionId, UncleId, TraceId, TraceFilter, LastHashes, CallAnalytics,
|
||||
ProvingBlockChainClient, ScheduleInfo, ImportSealedBlock, BroadcastProposalBlock, ImportBlock, StateOrBlock,
|
||||
Call, StateClient, EngineInfo, AccountData, BlockChain, BlockProducer, SealedBlockImporter, IoClient,
|
||||
BadBlocks,
|
||||
@@ -47,7 +47,7 @@ use header::{Header as BlockHeader, BlockNumber};
|
||||
use filter::Filter;
|
||||
use log_entry::LocalizedLogEntry;
|
||||
use receipt::{Receipt, LocalizedReceipt, TransactionOutcome};
|
||||
use error::{Error, ImportResult};
|
||||
use error::{Error, EthcoreResult};
|
||||
use vm::Schedule;
|
||||
use miner::{self, Miner, MinerService};
|
||||
use spec::Spec;
|
||||
@@ -118,7 +118,7 @@ pub struct TestBlockChainClient {
|
||||
}
|
||||
|
||||
/// Used for generating test client blocks.
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum EachBlockWith {
|
||||
/// Plain block.
|
||||
Nothing,
|
||||
@@ -242,69 +242,68 @@ impl TestBlockChainClient {
|
||||
*self.error_on_logs.write() = val;
|
||||
}
|
||||
|
||||
/// Add blocks to test client.
|
||||
pub fn add_blocks(&self, count: usize, with: EachBlockWith) {
|
||||
let len = self.numbers.read().len();
|
||||
for n in len..(len + count) {
|
||||
let mut header = BlockHeader::new();
|
||||
header.set_difficulty(From::from(n));
|
||||
header.set_parent_hash(self.last_hash.read().clone());
|
||||
header.set_number(n as BlockNumber);
|
||||
header.set_gas_limit(U256::from(1_000_000));
|
||||
header.set_extra_data(self.extra_data.clone());
|
||||
let uncles = match with {
|
||||
EachBlockWith::Uncle | EachBlockWith::UncleAndTransaction => {
|
||||
let mut uncles = RlpStream::new_list(1);
|
||||
let mut uncle_header = BlockHeader::new();
|
||||
uncle_header.set_difficulty(From::from(n));
|
||||
uncle_header.set_parent_hash(self.last_hash.read().clone());
|
||||
uncle_header.set_number(n as BlockNumber);
|
||||
uncles.append(&uncle_header);
|
||||
header.set_uncles_hash(keccak(uncles.as_raw()));
|
||||
uncles
|
||||
},
|
||||
_ => RlpStream::new_list(0)
|
||||
};
|
||||
let txs = match with {
|
||||
EachBlockWith::Transaction | EachBlockWith::UncleAndTransaction => {
|
||||
let mut txs = RlpStream::new_list(1);
|
||||
let keypair = Random.generate().unwrap();
|
||||
// Update nonces value
|
||||
self.nonces.write().insert(keypair.address(), U256::one());
|
||||
let tx = Transaction {
|
||||
action: Action::Create,
|
||||
value: U256::from(100),
|
||||
data: "3331600055".from_hex().unwrap(),
|
||||
gas: U256::from(100_000),
|
||||
gas_price: U256::from(200_000_000_000u64),
|
||||
nonce: U256::zero()
|
||||
};
|
||||
let signed_tx = tx.sign(keypair.secret(), None);
|
||||
txs.append(&signed_tx);
|
||||
txs.out()
|
||||
},
|
||||
_ => ::rlp::EMPTY_LIST_RLP.to_vec()
|
||||
};
|
||||
/// Add a block to test client.
|
||||
pub fn add_block<F>(&self, with: EachBlockWith, hook: F)
|
||||
where F: Fn(BlockHeader) -> BlockHeader
|
||||
{
|
||||
let n = self.numbers.read().len();
|
||||
|
||||
let mut rlp = RlpStream::new_list(3);
|
||||
rlp.append(&header);
|
||||
rlp.append_raw(&txs, 1);
|
||||
rlp.append_raw(uncles.as_raw(), 1);
|
||||
let unverified = Unverified::from_rlp(rlp.out()).unwrap();
|
||||
self.import_block(unverified).unwrap();
|
||||
}
|
||||
}
|
||||
let mut header = BlockHeader::new();
|
||||
header.set_difficulty(From::from(n));
|
||||
header.set_parent_hash(self.last_hash.read().clone());
|
||||
header.set_number(n as BlockNumber);
|
||||
header.set_gas_limit(U256::from(1_000_000));
|
||||
header.set_extra_data(self.extra_data.clone());
|
||||
|
||||
header = hook(header);
|
||||
|
||||
let uncles = match with {
|
||||
EachBlockWith::Uncle | EachBlockWith::UncleAndTransaction => {
|
||||
let mut uncles = RlpStream::new_list(1);
|
||||
let mut uncle_header = BlockHeader::new();
|
||||
uncle_header.set_difficulty(From::from(n));
|
||||
uncle_header.set_parent_hash(self.last_hash.read().clone());
|
||||
uncle_header.set_number(n as BlockNumber);
|
||||
uncles.append(&uncle_header);
|
||||
header.set_uncles_hash(keccak(uncles.as_raw()));
|
||||
uncles
|
||||
},
|
||||
_ => RlpStream::new_list(0)
|
||||
};
|
||||
let txs = match with {
|
||||
EachBlockWith::Transaction | EachBlockWith::UncleAndTransaction => {
|
||||
let mut txs = RlpStream::new_list(1);
|
||||
let keypair = Random.generate().unwrap();
|
||||
// Update nonces value
|
||||
self.nonces.write().insert(keypair.address(), U256::one());
|
||||
let tx = Transaction {
|
||||
action: Action::Create,
|
||||
value: U256::from(100),
|
||||
data: "3331600055".from_hex().unwrap(),
|
||||
gas: U256::from(100_000),
|
||||
gas_price: U256::from(200_000_000_000u64),
|
||||
nonce: U256::zero()
|
||||
};
|
||||
let signed_tx = tx.sign(keypair.secret(), None);
|
||||
txs.append(&signed_tx);
|
||||
txs.out()
|
||||
},
|
||||
_ => ::rlp::EMPTY_LIST_RLP.to_vec()
|
||||
};
|
||||
|
||||
/// Make a bad block by setting invalid extra data.
|
||||
pub fn corrupt_block(&self, n: BlockNumber) {
|
||||
let hash = self.block_hash(BlockId::Number(n)).unwrap();
|
||||
let mut header: BlockHeader = self.block_header(BlockId::Number(n)).unwrap().decode().expect("decoding failed");
|
||||
header.set_extra_data(b"This extra data is way too long to be considered valid".to_vec());
|
||||
let mut rlp = RlpStream::new_list(3);
|
||||
rlp.append(&header);
|
||||
rlp.append_raw(&::rlp::NULL_RLP, 1);
|
||||
rlp.append_raw(&::rlp::NULL_RLP, 1);
|
||||
self.blocks.write().insert(hash, rlp.out());
|
||||
rlp.append_raw(&txs, 1);
|
||||
rlp.append_raw(uncles.as_raw(), 1);
|
||||
let unverified = Unverified::from_rlp(rlp.out()).unwrap();
|
||||
self.import_block(unverified).unwrap();
|
||||
}
|
||||
|
||||
/// Add a sequence of blocks to test client.
|
||||
pub fn add_blocks(&self, count: usize, with: EachBlockWith) {
|
||||
for _ in 0..count {
|
||||
self.add_block(with, |header| header);
|
||||
}
|
||||
}
|
||||
|
||||
/// Make a bad block by setting invalid parent hash.
|
||||
@@ -416,7 +415,7 @@ impl ScheduleInfo for TestBlockChainClient {
|
||||
}
|
||||
|
||||
impl ImportSealedBlock for TestBlockChainClient {
|
||||
fn import_sealed_block(&self, _block: SealedBlock) -> ImportResult {
|
||||
fn import_sealed_block(&self, _block: SealedBlock) -> EthcoreResult<H256> {
|
||||
Ok(H256::default())
|
||||
}
|
||||
}
|
||||
@@ -523,7 +522,7 @@ impl RegistryInfo for TestBlockChainClient {
|
||||
}
|
||||
|
||||
impl ImportBlock for TestBlockChainClient {
|
||||
fn import_block(&self, unverified: Unverified) -> Result<H256, BlockImportError> {
|
||||
fn import_block(&self, unverified: Unverified) -> EthcoreResult<H256> {
|
||||
let header = unverified.header;
|
||||
let h = header.hash();
|
||||
let number: usize = header.number() as usize;
|
||||
@@ -687,6 +686,10 @@ impl BlockChainClient for TestBlockChainClient {
|
||||
self.receipts.read().get(&id).cloned()
|
||||
}
|
||||
|
||||
fn localized_block_receipts(&self, _id: BlockId) -> Option<Vec<LocalizedReceipt>> {
|
||||
Some(self.receipts.read().values().cloned().collect())
|
||||
}
|
||||
|
||||
fn logs(&self, filter: Filter) -> Result<Vec<LocalizedLogEntry>, BlockId> {
|
||||
match self.error_on_logs.read().as_ref() {
|
||||
Some(id) => return Err(id.clone()),
|
||||
@@ -786,16 +789,14 @@ impl BlockChainClient for TestBlockChainClient {
|
||||
None
|
||||
}
|
||||
|
||||
fn block_receipts(&self, hash: &H256) -> Option<Bytes> {
|
||||
fn block_receipts(&self, hash: &H256) -> Option<BlockReceipts> {
|
||||
// starts with 'f' ?
|
||||
if *hash > H256::from("f000000000000000000000000000000000000000000000000000000000000000") {
|
||||
let receipt = BlockReceipts::new(vec![Receipt::new(
|
||||
TransactionOutcome::StateRoot(H256::zero()),
|
||||
U256::zero(),
|
||||
vec![])]);
|
||||
let mut rlp = RlpStream::new();
|
||||
rlp.append(&receipt);
|
||||
return Some(rlp.out());
|
||||
return Some(receipt);
|
||||
}
|
||||
None
|
||||
}
|
||||
@@ -883,7 +884,7 @@ impl IoClient for TestBlockChainClient {
|
||||
self.miner.import_external_transactions(self, txs);
|
||||
}
|
||||
|
||||
fn queue_ancient_block(&self, unverified: Unverified, _r: Bytes) -> Result<H256, BlockImportError> {
|
||||
fn queue_ancient_block(&self, unverified: Unverified, _r: Bytes) -> EthcoreResult<H256> {
|
||||
self.import_block(unverified)
|
||||
}
|
||||
|
||||
|
||||
@@ -20,11 +20,11 @@ use std::sync::Arc;
|
||||
use itertools::Itertools;
|
||||
|
||||
use block::{OpenBlock, SealedBlock, ClosedBlock};
|
||||
use blockchain::TreeRoute;
|
||||
use blockchain::{BlockReceipts, TreeRoute};
|
||||
use client::Mode;
|
||||
use encoded;
|
||||
use vm::LastHashes;
|
||||
use error::{Error, ImportResult, CallError, BlockImportError};
|
||||
use error::{Error, CallError, EthcoreResult};
|
||||
use evm::Schedule;
|
||||
use executive::Executed;
|
||||
use filter::Filter;
|
||||
@@ -42,7 +42,7 @@ use engines::EthEngine;
|
||||
use ethereum_types::{H256, U256, Address};
|
||||
use ethcore_miner::pool::VerifiedTransaction;
|
||||
use bytes::Bytes;
|
||||
use hashdb::DBValue;
|
||||
use kvdb::DBValue;
|
||||
|
||||
use types::ids::*;
|
||||
use types::basic_account::BasicAccount;
|
||||
@@ -168,7 +168,7 @@ pub trait RegistryInfo {
|
||||
/// Provides methods to import block into blockchain
|
||||
pub trait ImportBlock {
|
||||
/// Import a block into the blockchain.
|
||||
fn import_block(&self, block: Unverified) -> Result<H256, BlockImportError>;
|
||||
fn import_block(&self, block: Unverified) -> EthcoreResult<H256>;
|
||||
}
|
||||
|
||||
/// Provides `call_contract` method
|
||||
@@ -205,7 +205,7 @@ pub trait IoClient: Sync + Send {
|
||||
fn queue_transactions(&self, transactions: Vec<Bytes>, peer_id: usize);
|
||||
|
||||
/// Queue block import with transaction receipts. Does no sealing and transaction validation.
|
||||
fn queue_ancient_block(&self, block_bytes: Unverified, receipts_bytes: Bytes) -> Result<H256, BlockImportError>;
|
||||
fn queue_ancient_block(&self, block_bytes: Unverified, receipts_bytes: Bytes) -> EthcoreResult<H256>;
|
||||
|
||||
/// Queue conensus engine message.
|
||||
fn queue_consensus_message(&self, message: Bytes);
|
||||
@@ -281,6 +281,9 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra
|
||||
/// Get transaction receipt with given hash.
|
||||
fn transaction_receipt(&self, id: TransactionId) -> Option<LocalizedReceipt>;
|
||||
|
||||
/// Get localized receipts for all transaction in given block.
|
||||
fn localized_block_receipts(&self, id: BlockId) -> Option<Vec<LocalizedReceipt>>;
|
||||
|
||||
/// Get a tree route between `from` and `to`.
|
||||
/// See `BlockChain::tree_route`.
|
||||
fn tree_route(&self, from: &H256, to: &H256) -> Option<TreeRoute>;
|
||||
@@ -291,12 +294,17 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra
|
||||
/// Get latest state node
|
||||
fn state_data(&self, hash: &H256) -> Option<Bytes>;
|
||||
|
||||
/// Get raw block receipts data by block header hash.
|
||||
fn block_receipts(&self, hash: &H256) -> Option<Bytes>;
|
||||
/// Get block receipts data by block header hash.
|
||||
fn block_receipts(&self, hash: &H256) -> Option<BlockReceipts>;
|
||||
|
||||
/// Get block queue information.
|
||||
fn queue_info(&self) -> BlockQueueInfo;
|
||||
|
||||
/// Returns true if block queue is empty.
|
||||
fn is_queue_empty(&self) -> bool {
|
||||
self.queue_info().is_empty()
|
||||
}
|
||||
|
||||
/// Clear block queue and abort all import activity.
|
||||
fn clear_queue(&self);
|
||||
|
||||
@@ -414,7 +422,7 @@ pub trait ScheduleInfo {
|
||||
///Provides `import_sealed_block` method
|
||||
pub trait ImportSealedBlock {
|
||||
/// Import sealed block. Skips all verifications.
|
||||
fn import_sealed_block(&self, block: SealedBlock) -> ImportResult;
|
||||
fn import_sealed_block(&self, block: SealedBlock) -> EthcoreResult<H256>;
|
||||
}
|
||||
|
||||
/// Provides `broadcast_proposal_block` method
|
||||
|
||||
@@ -96,7 +96,10 @@ impl RollingFinality {
|
||||
}
|
||||
|
||||
/// Get an iterator over stored hashes in order.
|
||||
pub fn unfinalized_hashes(&self) -> Iter { Iter(self.headers.iter()) }
|
||||
#[cfg(test)]
|
||||
pub fn unfinalized_hashes(&self) -> impl Iterator<Item=&H256> {
|
||||
self.headers.iter().map(|(h, _)| h)
|
||||
}
|
||||
|
||||
/// Get the validator set.
|
||||
pub fn validators(&self) -> &SimpleList { &self.signers }
|
||||
@@ -145,16 +148,6 @@ impl RollingFinality {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Iter<'a>(::std::collections::vec_deque::Iter<'a, (H256, Vec<Address>)>);
|
||||
|
||||
impl<'a> Iterator for Iter<'a> {
|
||||
type Item = H256;
|
||||
|
||||
fn next(&mut self) -> Option<H256> {
|
||||
self.0.next().map(|&(h, _)| h)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ethereum_types::{H256, Address};
|
||||
@@ -220,7 +213,7 @@ mod tests {
|
||||
|
||||
// only the last hash has < 51% of authorities' signatures
|
||||
assert_eq!(finality.unfinalized_hashes().count(), 1);
|
||||
assert_eq!(finality.unfinalized_hashes().next(), Some(hashes[11].0));
|
||||
assert_eq!(finality.unfinalized_hashes().next(), Some(&hashes[11].0));
|
||||
assert_eq!(finality.subchain_head(), Some(hashes[11].0));
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -110,7 +110,7 @@ impl Engine<EthereumMachine> for BasicAuthority {
|
||||
if self.validators.contains(header.parent_hash(), author) {
|
||||
// account should be pernamently unlocked, otherwise sealing will fail
|
||||
if let Ok(signature) = self.sign(header.bare_hash()) {
|
||||
return Seal::Regular(vec![::rlp::encode(&(&H520::from(signature) as &[u8])).into_vec()]);
|
||||
return Seal::Regular(vec![::rlp::encode(&(&H520::from(signature) as &[u8]))]);
|
||||
} else {
|
||||
trace!(target: "basicauthority", "generate_seal: FAIL: accounts secret key unavailable");
|
||||
}
|
||||
@@ -150,6 +150,7 @@ impl Engine<EthereumMachine> for BasicAuthority {
|
||||
fn is_epoch_end(
|
||||
&self,
|
||||
chain_head: &Header,
|
||||
_finalized: &[H256],
|
||||
_chain: &super::Headers<Header>,
|
||||
_transition_store: &super::PendingTransitionStore,
|
||||
) -> Option<Vec<u8>> {
|
||||
@@ -159,6 +160,15 @@ impl Engine<EthereumMachine> for BasicAuthority {
|
||||
self.validators.is_epoch_end(first, chain_head)
|
||||
}
|
||||
|
||||
fn is_epoch_end_light(
|
||||
&self,
|
||||
chain_head: &Header,
|
||||
chain: &super::Headers<Header>,
|
||||
transition_store: &super::PendingTransitionStore,
|
||||
) -> Option<Vec<u8>> {
|
||||
self.is_epoch_end(chain_head, &[], chain, transition_store)
|
||||
}
|
||||
|
||||
fn epoch_verifier<'a>(&self, header: &Header, proof: &'a [u8]) -> ConstructedVerifier<'a, EthereumMachine> {
|
||||
let first = header.number() == 0;
|
||||
|
||||
@@ -234,7 +244,7 @@ mod tests {
|
||||
fn can_do_signature_verification_fail() {
|
||||
let engine = new_test_authority().engine;
|
||||
let mut header: Header = Header::default();
|
||||
header.set_seal(vec![::rlp::encode(&H520::default()).into_vec()]);
|
||||
header.set_seal(vec![::rlp::encode(&H520::default())]);
|
||||
|
||||
let verify_result = engine.verify_block_external(&header);
|
||||
assert!(verify_result.is_err());
|
||||
|
||||
@@ -30,7 +30,7 @@ use trace;
|
||||
use types::BlockNumber;
|
||||
use super::{SystemOrCodeCall, SystemOrCodeCallKind};
|
||||
|
||||
use_contract!(block_reward_contract, "BlockReward", "res/contracts/block_reward.json");
|
||||
use_contract!(block_reward_contract, "res/contracts/block_reward.json");
|
||||
|
||||
/// The kind of block reward.
|
||||
/// Depending on the consensus engine the allocated block reward might have
|
||||
@@ -81,7 +81,6 @@ impl Into<trace::RewardType> for RewardKind {
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub struct BlockRewardContract {
|
||||
kind: SystemOrCodeCallKind,
|
||||
block_reward_contract: block_reward_contract::BlockReward,
|
||||
}
|
||||
|
||||
impl BlockRewardContract {
|
||||
@@ -89,7 +88,6 @@ impl BlockRewardContract {
|
||||
pub fn new(kind: SystemOrCodeCallKind) -> BlockRewardContract {
|
||||
BlockRewardContract {
|
||||
kind,
|
||||
block_reward_contract: block_reward_contract::BlockReward::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,9 +112,7 @@ impl BlockRewardContract {
|
||||
beneficiaries: &[(Address, RewardKind)],
|
||||
caller: &mut SystemOrCodeCall,
|
||||
) -> Result<Vec<(Address, U256)>, Error> {
|
||||
let reward = self.block_reward_contract.functions().reward();
|
||||
|
||||
let input = reward.input(
|
||||
let input = block_reward_contract::functions::reward::encode_input(
|
||||
beneficiaries.iter().map(|&(address, _)| H160::from(address)),
|
||||
beneficiaries.iter().map(|&(_, ref reward_kind)| u16::from(*reward_kind)),
|
||||
);
|
||||
|
||||
@@ -18,7 +18,7 @@ use engines::{Engine, Seal};
|
||||
use parity_machine::{Machine, Transactions, TotalScoredHeader};
|
||||
|
||||
/// `InstantSeal` params.
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Default, Debug, PartialEq)]
|
||||
pub struct InstantSealParams {
|
||||
/// Whether to use millisecond timestamp
|
||||
pub millisecond_timestamp: bool,
|
||||
@@ -120,7 +120,7 @@ mod tests {
|
||||
|
||||
assert!(engine.verify_block_basic(&header).is_ok());
|
||||
|
||||
header.set_seal(vec![::rlp::encode(&H520::default()).into_vec()]);
|
||||
header.set_seal(vec![::rlp::encode(&H520::default())]);
|
||||
|
||||
assert!(engine.verify_block_unordered(&header).is_ok());
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ pub mod epoch;
|
||||
pub use self::authority_round::AuthorityRound;
|
||||
pub use self::basic_authority::BasicAuthority;
|
||||
pub use self::epoch::{EpochVerifier, Transition as EpochTransition};
|
||||
pub use self::instant_seal::InstantSeal;
|
||||
pub use self::instant_seal::{InstantSeal, InstantSealParams};
|
||||
pub use self::null_engine::NullEngine;
|
||||
pub use self::tendermint::Tendermint;
|
||||
|
||||
@@ -44,7 +44,7 @@ use self::epoch::PendingTransition;
|
||||
|
||||
use account_provider::AccountProvider;
|
||||
use builtin::Builtin;
|
||||
use vm::{EnvInfo, Schedule, CreateContractAddress};
|
||||
use vm::{EnvInfo, Schedule, CreateContractAddress, CallType, ActionValue};
|
||||
use error::Error;
|
||||
use header::{Header, BlockNumber};
|
||||
use snapshot::SnapshotComponents;
|
||||
@@ -163,8 +163,10 @@ pub fn default_system_or_code_call<'a>(machine: &'a ::machine::EthereumMachine,
|
||||
None,
|
||||
Some(code),
|
||||
Some(code_hash),
|
||||
Some(ActionValue::Apparent(U256::zero())),
|
||||
U256::max_value(),
|
||||
Some(data),
|
||||
Some(CallType::StaticCall),
|
||||
)
|
||||
},
|
||||
};
|
||||
@@ -252,6 +254,9 @@ pub trait Engine<M: Machine>: Sync + Send {
|
||||
/// The number of generations back that uncles can be.
|
||||
fn maximum_uncle_age(&self) -> usize { 6 }
|
||||
|
||||
/// Optional maximum gas limit.
|
||||
fn maximum_gas_limit(&self) -> Option<U256> { None }
|
||||
|
||||
/// Block transformation functions, before the transactions.
|
||||
/// `epoch_begin` set to true if this block kicks off an epoch.
|
||||
fn on_new_block(
|
||||
@@ -333,10 +338,30 @@ pub trait Engine<M: Machine>: Sync + Send {
|
||||
///
|
||||
/// This either means that an immediate transition occurs or a block signalling transition
|
||||
/// has reached finality. The `Headers` given are not guaranteed to return any blocks
|
||||
/// from any epoch other than the current.
|
||||
/// from any epoch other than the current. The client must keep track of finality and provide
|
||||
/// the latest finalized headers to check against the transition store.
|
||||
///
|
||||
/// Return optional transition proof.
|
||||
fn is_epoch_end(
|
||||
&self,
|
||||
_chain_head: &M::Header,
|
||||
_finalized: &[H256],
|
||||
_chain: &Headers<M::Header>,
|
||||
_transition_store: &PendingTransitionStore,
|
||||
) -> Option<Vec<u8>> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Whether a block is the end of an epoch.
|
||||
///
|
||||
/// This either means that an immediate transition occurs or a block signalling transition
|
||||
/// has reached finality. The `Headers` given are not guaranteed to return any blocks
|
||||
/// from any epoch other than the current. This is a specialized method to use for light
|
||||
/// clients since the light client doesn't track finality of all blocks, and therefore finality
|
||||
/// for blocks in the current epoch is built inside this method by the engine.
|
||||
///
|
||||
/// Return optional transition proof.
|
||||
fn is_epoch_end_light(
|
||||
&self,
|
||||
_chain_head: &M::Header,
|
||||
_chain: &Headers<M::Header>,
|
||||
@@ -404,7 +429,7 @@ pub trait Engine<M: Machine>: Sync + Send {
|
||||
|
||||
/// Gather all ancestry actions. Called at the last stage when a block is committed. The Engine must guarantee that
|
||||
/// the ancestry exists.
|
||||
fn ancestry_actions(&self, _block: &M::LiveBlock, _ancestry: &mut Iterator<Item=M::ExtendedHeader>) -> Vec<AncestryAction> {
|
||||
fn ancestry_actions(&self, _header: &M::Header, _ancestry: &mut Iterator<Item=M::ExtendedHeader>) -> Vec<AncestryAction> {
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
|
||||
@@ -231,7 +231,7 @@ mod tests {
|
||||
},
|
||||
block_hash: Some(keccak("1")),
|
||||
};
|
||||
let raw_rlp = ::rlp::encode(&message).into_vec();
|
||||
let raw_rlp = ::rlp::encode(&message);
|
||||
let rlp = Rlp::new(&raw_rlp);
|
||||
assert_eq!(Ok(message), rlp.as_val());
|
||||
|
||||
@@ -268,8 +268,8 @@ mod tests {
|
||||
fn proposal_message() {
|
||||
let mut header = Header::default();
|
||||
let seal = vec![
|
||||
::rlp::encode(&0u8).into_vec(),
|
||||
::rlp::encode(&H520::default()).into_vec(),
|
||||
::rlp::encode(&0u8),
|
||||
::rlp::encode(&H520::default()),
|
||||
Vec::new()
|
||||
];
|
||||
|
||||
|
||||
@@ -407,9 +407,9 @@ impl Tendermint {
|
||||
let precommits = self.votes.round_signatures(vote_step, &bh);
|
||||
trace!(target: "engine", "Collected seal: {:?}", precommits);
|
||||
let seal = vec![
|
||||
::rlp::encode(&vote_step.view).into_vec(),
|
||||
::rlp::encode(&vote_step.view),
|
||||
::rlp::NULL_RLP.to_vec(),
|
||||
::rlp::encode_list(&precommits).into_vec()
|
||||
::rlp::encode_list(&precommits)
|
||||
];
|
||||
self.submit_seal(bh, seal);
|
||||
self.votes.throw_out_old(&vote_step);
|
||||
@@ -491,8 +491,8 @@ impl Engine<EthereumMachine> for Tendermint {
|
||||
*self.proposal.write() = bh;
|
||||
*self.proposal_parent.write() = header.parent_hash().clone();
|
||||
Seal::Proposal(vec![
|
||||
::rlp::encode(&view).into_vec(),
|
||||
::rlp::encode(&signature).into_vec(),
|
||||
::rlp::encode(&view),
|
||||
::rlp::encode(&signature),
|
||||
::rlp::EMPTY_LIST_RLP.to_vec()
|
||||
])
|
||||
} else {
|
||||
@@ -520,7 +520,7 @@ impl Engine<EthereumMachine> for Tendermint {
|
||||
self.broadcast_message(rlp.as_raw().to_vec());
|
||||
if let Some(double) = self.votes.vote(message.clone(), sender) {
|
||||
let height = message.vote_step.height as BlockNumber;
|
||||
self.validators.report_malicious(&sender, height, height, ::rlp::encode(&double).into_vec());
|
||||
self.validators.report_malicious(&sender, height, height, ::rlp::encode(&double));
|
||||
return Err(EngineError::DoubleVote(sender));
|
||||
}
|
||||
trace!(target: "engine", "Handling a valid {:?} from {}.", message, sender);
|
||||
@@ -635,6 +635,7 @@ impl Engine<EthereumMachine> for Tendermint {
|
||||
fn is_epoch_end(
|
||||
&self,
|
||||
chain_head: &Header,
|
||||
_finalized: &[H256],
|
||||
_chain: &super::Headers<Header>,
|
||||
transition_store: &super::PendingTransitionStore,
|
||||
) -> Option<Vec<u8>> {
|
||||
@@ -652,6 +653,15 @@ impl Engine<EthereumMachine> for Tendermint {
|
||||
None
|
||||
}
|
||||
|
||||
fn is_epoch_end_light(
|
||||
&self,
|
||||
chain_head: &Header,
|
||||
chain: &super::Headers<Header>,
|
||||
transition_store: &super::PendingTransitionStore,
|
||||
) -> Option<Vec<u8>> {
|
||||
self.is_epoch_end(chain_head, &[], chain, transition_store)
|
||||
}
|
||||
|
||||
fn epoch_verifier<'a>(&self, _header: &Header, proof: &'a [u8]) -> ConstructedVerifier<'a, EthereumMachine> {
|
||||
let (signal_number, set_proof, finality_proof) = match destructure_proofs(proof) {
|
||||
Ok(x) => x,
|
||||
@@ -693,7 +703,6 @@ impl Engine<EthereumMachine> for Tendermint {
|
||||
}
|
||||
|
||||
fn stop(&self) {
|
||||
self.step_service.stop()
|
||||
}
|
||||
|
||||
fn is_proposal(&self, header: &Header) -> bool {
|
||||
@@ -824,8 +833,8 @@ mod tests {
|
||||
let vote_info = message_info_rlp(&VoteStep::new(header.number() as Height, view, Step::Propose), Some(header.bare_hash()));
|
||||
let signature = tap.sign(*author, None, keccak(vote_info)).unwrap();
|
||||
vec![
|
||||
::rlp::encode(&view).into_vec(),
|
||||
::rlp::encode(&H520::from(signature)).into_vec(),
|
||||
::rlp::encode(&view),
|
||||
::rlp::encode(&H520::from(signature)),
|
||||
::rlp::EMPTY_LIST_RLP.to_vec()
|
||||
]
|
||||
}
|
||||
@@ -929,7 +938,7 @@ mod tests {
|
||||
let signature1 = tap.sign(proposer, None, keccak(&vote_info)).unwrap();
|
||||
|
||||
seal[1] = ::rlp::NULL_RLP.to_vec();
|
||||
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone())]).into_vec();
|
||||
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone())]);
|
||||
header.set_seal(seal.clone());
|
||||
|
||||
// One good signature is not enough.
|
||||
@@ -941,7 +950,7 @@ mod tests {
|
||||
let voter = insert_and_unlock(&tap, "0");
|
||||
let signature0 = tap.sign(voter, None, keccak(&vote_info)).unwrap();
|
||||
|
||||
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone()), H520::from(signature0.clone())]).into_vec();
|
||||
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone()), H520::from(signature0.clone())]);
|
||||
header.set_seal(seal.clone());
|
||||
|
||||
assert!(engine.verify_block_external(&header).is_ok());
|
||||
@@ -949,7 +958,7 @@ mod tests {
|
||||
let bad_voter = insert_and_unlock(&tap, "101");
|
||||
let bad_signature = tap.sign(bad_voter, None, keccak(vote_info)).unwrap();
|
||||
|
||||
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1), H520::from(bad_signature)]).into_vec();
|
||||
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1), H520::from(bad_signature)]);
|
||||
header.set_seal(seal);
|
||||
|
||||
// One good and one bad signature.
|
||||
@@ -1085,7 +1094,7 @@ mod tests {
|
||||
let signature0 = tap.sign(voter, None, keccak(&vote_info)).unwrap();
|
||||
|
||||
seal[1] = ::rlp::NULL_RLP.to_vec();
|
||||
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone())]).into_vec();
|
||||
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone())]);
|
||||
header.set_seal(seal.clone());
|
||||
|
||||
let epoch_verifier = super::EpochVerifier {
|
||||
@@ -1113,7 +1122,7 @@ mod tests {
|
||||
_ => panic!(),
|
||||
}
|
||||
|
||||
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone()), H520::from(signature0.clone())]).into_vec();
|
||||
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone()), H520::from(signature0.clone())]);
|
||||
header.set_seal(seal.clone());
|
||||
|
||||
assert!(epoch_verifier.verify_light(&header).is_ok());
|
||||
@@ -1121,7 +1130,7 @@ mod tests {
|
||||
let bad_voter = insert_and_unlock(&tap, "101");
|
||||
let bad_signature = tap.sign(bad_voter, None, keccak(&vote_info)).unwrap();
|
||||
|
||||
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1), H520::from(bad_signature)]).into_vec();
|
||||
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1), H520::from(bad_signature)]);
|
||||
header.set_seal(seal);
|
||||
|
||||
// One good and one bad signature.
|
||||
|
||||
@@ -30,13 +30,12 @@ use machine::{AuxiliaryData, Call, EthereumMachine};
|
||||
use super::{ValidatorSet, SimpleList, SystemCall};
|
||||
use super::safe_contract::ValidatorSafeContract;
|
||||
|
||||
use_contract!(validator_report, "ValidatorReport", "res/contracts/validator_report.json");
|
||||
use_contract!(validator_report, "res/contracts/validator_report.json");
|
||||
|
||||
/// A validator contract with reporting.
|
||||
pub struct ValidatorContract {
|
||||
contract_address: Address,
|
||||
validators: ValidatorSafeContract,
|
||||
provider: validator_report::ValidatorReport,
|
||||
client: RwLock<Option<Weak<EngineClient>>>, // TODO [keorn]: remove
|
||||
}
|
||||
|
||||
@@ -45,7 +44,6 @@ impl ValidatorContract {
|
||||
ValidatorContract {
|
||||
contract_address,
|
||||
validators: ValidatorSafeContract::new(contract_address),
|
||||
provider: validator_report::ValidatorReport::default(),
|
||||
client: RwLock::new(None),
|
||||
}
|
||||
}
|
||||
@@ -111,7 +109,7 @@ impl ValidatorSet for ValidatorContract {
|
||||
}
|
||||
|
||||
fn report_malicious(&self, address: &Address, _set_block: BlockNumber, block: BlockNumber, proof: Bytes) {
|
||||
let data = self.provider.functions().report_malicious().input(*address, block, proof);
|
||||
let data = validator_report::functions::report_malicious::encode_input(*address, block, proof);
|
||||
match self.transact(data) {
|
||||
Ok(_) => warn!(target: "engine", "Reported malicious validator {}", address),
|
||||
Err(s) => warn!(target: "engine", "Validator {} could not be reported {}", address, s),
|
||||
@@ -119,7 +117,7 @@ impl ValidatorSet for ValidatorContract {
|
||||
}
|
||||
|
||||
fn report_benign(&self, address: &Address, _set_block: BlockNumber, block: BlockNumber) {
|
||||
let data = self.provider.functions().report_benign().input(*address, block);
|
||||
let data = validator_report::functions::report_benign::encode_input(*address, block);
|
||||
match self.transact(data) {
|
||||
Ok(_) => warn!(target: "engine", "Reported benign validator misbehaviour {}", address),
|
||||
Err(s) => warn!(target: "engine", "Validator {} could not be reported {}", address, s),
|
||||
@@ -174,7 +172,7 @@ mod tests {
|
||||
|
||||
// Check a block that is a bit in future, reject it but don't report the validator.
|
||||
let mut header = Header::default();
|
||||
let seal = vec![encode(&4u8).into_vec(), encode(&(&H520::default() as &[u8])).into_vec()];
|
||||
let seal = vec![encode(&4u8), encode(&(&H520::default() as &[u8]))];
|
||||
header.set_seal(seal);
|
||||
header.set_author(v1);
|
||||
header.set_number(2);
|
||||
@@ -185,7 +183,7 @@ mod tests {
|
||||
|
||||
// Now create one that is more in future. That one should be rejected and validator should be reported.
|
||||
let mut header = Header::default();
|
||||
let seal = vec![encode(&8u8).into_vec(), encode(&(&H520::default() as &[u8])).into_vec()];
|
||||
let seal = vec![encode(&8u8), encode(&(&H520::default() as &[u8]))];
|
||||
header.set_seal(seal);
|
||||
header.set_author(v1);
|
||||
header.set_number(2);
|
||||
|
||||
@@ -33,8 +33,9 @@ use std::sync::{Weak, Arc};
|
||||
use super::{SystemCall, ValidatorSet};
|
||||
use super::simple_list::SimpleList;
|
||||
use unexpected::Mismatch;
|
||||
use ethabi::FunctionOutputDecoder;
|
||||
|
||||
use_contract!(validator_set, "ValidatorSet", "res/contracts/validator_set.json");
|
||||
use_contract!(validator_set, "res/contracts/validator_set.json");
|
||||
|
||||
const MEMOIZE_CAPACITY: usize = 500;
|
||||
|
||||
@@ -50,12 +51,11 @@ lazy_static! {
|
||||
struct StateProof {
|
||||
contract_address: Address,
|
||||
header: Header,
|
||||
provider: validator_set::ValidatorSet,
|
||||
}
|
||||
|
||||
impl ::engines::StateDependentProof<EthereumMachine> for StateProof {
|
||||
fn generate_proof(&self, caller: &Call) -> Result<Vec<u8>, String> {
|
||||
prove_initial(&self.provider, self.contract_address, &self.header, caller)
|
||||
prove_initial(self.contract_address, &self.header, caller)
|
||||
}
|
||||
|
||||
fn check_proof(&self, machine: &EthereumMachine, proof: &[u8]) -> Result<(), String> {
|
||||
@@ -65,7 +65,7 @@ impl ::engines::StateDependentProof<EthereumMachine> for StateProof {
|
||||
return Err("wrong header in proof".into());
|
||||
}
|
||||
|
||||
check_first_proof(machine, &self.provider, self.contract_address, header, &state_items).map(|_| ())
|
||||
check_first_proof(machine, self.contract_address, header, &state_items).map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,6 @@ impl ::engines::StateDependentProof<EthereumMachine> for StateProof {
|
||||
pub struct ValidatorSafeContract {
|
||||
contract_address: Address,
|
||||
validators: RwLock<MemoryLruCache<H256, SimpleList>>,
|
||||
provider: validator_set::ValidatorSet,
|
||||
client: RwLock<Option<Weak<EngineClient>>>, // TODO [keorn]: remove
|
||||
}
|
||||
|
||||
@@ -89,7 +88,7 @@ fn encode_first_proof(header: &Header, state_items: &[Vec<u8>]) -> Bytes {
|
||||
}
|
||||
|
||||
// check a first proof: fetch the validator set at the given block.
|
||||
fn check_first_proof(machine: &EthereumMachine, provider: &validator_set::ValidatorSet, contract_address: Address, old_header: Header, state_items: &[DBValue])
|
||||
fn check_first_proof(machine: &EthereumMachine, contract_address: Address, old_header: Header, state_items: &[DBValue])
|
||||
-> Result<Vec<Address>, String>
|
||||
{
|
||||
use transaction::{Action, Transaction};
|
||||
@@ -114,31 +113,31 @@ fn check_first_proof(machine: &EthereumMachine, provider: &validator_set::Valida
|
||||
|
||||
// check state proof using given machine.
|
||||
let number = old_header.number();
|
||||
provider.functions().get_validators().call(&|data| {
|
||||
let from = Address::default();
|
||||
let tx = Transaction {
|
||||
nonce: machine.account_start_nonce(number),
|
||||
action: Action::Call(contract_address),
|
||||
gas: PROVIDED_GAS.into(),
|
||||
gas_price: U256::default(),
|
||||
value: U256::default(),
|
||||
data,
|
||||
}.fake_sign(from);
|
||||
let (data, decoder) = validator_set::functions::get_validators::call();
|
||||
|
||||
let res = ::state::check_proof(
|
||||
state_items,
|
||||
*old_header.state_root(),
|
||||
&tx,
|
||||
machine,
|
||||
&env_info,
|
||||
);
|
||||
let from = Address::default();
|
||||
let tx = Transaction {
|
||||
nonce: machine.account_start_nonce(number),
|
||||
action: Action::Call(contract_address),
|
||||
gas: PROVIDED_GAS.into(),
|
||||
gas_price: U256::default(),
|
||||
value: U256::default(),
|
||||
data,
|
||||
}.fake_sign(from);
|
||||
|
||||
match res {
|
||||
::state::ProvedExecution::BadProof => Err("Bad proof".into()),
|
||||
::state::ProvedExecution::Failed(e) => Err(format!("Failed call: {}", e)),
|
||||
::state::ProvedExecution::Complete(e) => Ok(e.output),
|
||||
}
|
||||
}).map_err(|err| err.to_string())
|
||||
let res = ::state::check_proof(
|
||||
state_items,
|
||||
*old_header.state_root(),
|
||||
&tx,
|
||||
machine,
|
||||
&env_info,
|
||||
);
|
||||
|
||||
match res {
|
||||
::state::ProvedExecution::BadProof => Err("Bad proof".into()),
|
||||
::state::ProvedExecution::Failed(e) => Err(format!("Failed call: {}", e)),
|
||||
::state::ProvedExecution::Complete(e) => decoder.decode(&e.output).map_err(|e| e.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
fn decode_first_proof(rlp: &Rlp) -> Result<(Header, Vec<DBValue>), ::error::Error> {
|
||||
@@ -158,7 +157,7 @@ fn decode_first_proof(rlp: &Rlp) -> Result<(Header, Vec<DBValue>), ::error::Erro
|
||||
fn encode_proof(header: &Header, receipts: &[Receipt]) -> Bytes {
|
||||
let mut stream = RlpStream::new_list(2);
|
||||
stream.append(header).append_list(receipts);
|
||||
stream.drain().into_vec()
|
||||
stream.drain()
|
||||
}
|
||||
|
||||
fn decode_proof(rlp: &Rlp) -> Result<(Header, Vec<Receipt>), ::error::Error> {
|
||||
@@ -167,32 +166,26 @@ fn decode_proof(rlp: &Rlp) -> Result<(Header, Vec<Receipt>), ::error::Error> {
|
||||
|
||||
// given a provider and caller, generate proof. this will just be a state proof
|
||||
// of `getValidators`.
|
||||
fn prove_initial(provider: &validator_set::ValidatorSet, contract_address: Address, header: &Header, caller: &Call) -> Result<Vec<u8>, String> {
|
||||
fn prove_initial(contract_address: Address, header: &Header, caller: &Call) -> Result<Vec<u8>, String> {
|
||||
use std::cell::RefCell;
|
||||
|
||||
let epoch_proof = RefCell::new(None);
|
||||
let res = {
|
||||
let caller = |data| {
|
||||
let (result, proof) = caller(contract_address, data)?;
|
||||
*epoch_proof.borrow_mut() = Some(encode_first_proof(header, &proof));
|
||||
Ok(result)
|
||||
};
|
||||
|
||||
provider.functions().get_validators().call(&caller)
|
||||
.map_err(|err| err.to_string())
|
||||
let validators = {
|
||||
let (data, decoder) = validator_set::functions::get_validators::call();
|
||||
let (value, proof) = caller(contract_address, data)?;
|
||||
*epoch_proof.borrow_mut() = Some(encode_first_proof(header, &proof));
|
||||
decoder.decode(&value).map_err(|e| e.to_string())?
|
||||
};
|
||||
|
||||
res.map(|validators| {
|
||||
let proof = epoch_proof.into_inner().expect("epoch_proof always set after call; qed");
|
||||
let proof = epoch_proof.into_inner().expect("epoch_proof always set after call; qed");
|
||||
|
||||
trace!(target: "engine", "obtained proof for initial set: {} validators, {} bytes",
|
||||
validators.len(), proof.len());
|
||||
trace!(target: "engine", "obtained proof for initial set: {} validators, {} bytes",
|
||||
validators.len(), proof.len());
|
||||
|
||||
info!(target: "engine", "Signal for switch to contract-based validator set.");
|
||||
info!(target: "engine", "Initial contract validators: {:?}", validators);
|
||||
info!(target: "engine", "Signal for switch to contract-based validator set.");
|
||||
info!(target: "engine", "Initial contract validators: {:?}", validators);
|
||||
|
||||
proof
|
||||
})
|
||||
Ok(proof)
|
||||
}
|
||||
|
||||
impl ValidatorSafeContract {
|
||||
@@ -200,7 +193,6 @@ impl ValidatorSafeContract {
|
||||
ValidatorSafeContract {
|
||||
contract_address,
|
||||
validators: RwLock::new(MemoryLruCache::new(MEMOIZE_CAPACITY)),
|
||||
provider: validator_set::ValidatorSet::default(),
|
||||
client: RwLock::new(None),
|
||||
}
|
||||
}
|
||||
@@ -208,8 +200,11 @@ impl ValidatorSafeContract {
|
||||
/// Queries the state and gets the set of validators.
|
||||
fn get_list(&self, caller: &Call) -> Option<SimpleList> {
|
||||
let contract_address = self.contract_address;
|
||||
let caller = move |data| caller(contract_address, data).map(|x| x.0);
|
||||
match self.provider.functions().get_validators().call(&caller) {
|
||||
|
||||
let (data, decoder) = validator_set::functions::get_validators::call();
|
||||
let value = caller(contract_address, data).and_then(|x| decoder.decode(&x.0).map_err(|e| e.to_string()));
|
||||
|
||||
match value {
|
||||
Ok(new) => {
|
||||
debug!(target: "engine", "Set of validators obtained: {:?}", new);
|
||||
Some(SimpleList::new(new))
|
||||
@@ -259,7 +254,6 @@ impl ValidatorSafeContract {
|
||||
log.topics[1] == *header.parent_hash()
|
||||
};
|
||||
|
||||
let event = self.provider.events().initiate_change();
|
||||
//// iterate in reverse because only the _last_ change in a given
|
||||
//// block actually has any effect.
|
||||
//// the contract should only increment the nonce once.
|
||||
@@ -269,7 +263,7 @@ impl ValidatorSafeContract {
|
||||
.flat_map(|r| r.logs.iter())
|
||||
.filter(move |l| check_log(l))
|
||||
.filter_map(|log| {
|
||||
event.parse_log((log.topics.clone(), log.data.clone()).into()).ok()
|
||||
validator_set::events::initiate_change::parse_log((log.topics.clone(), log.data.clone()).into()).ok()
|
||||
});
|
||||
|
||||
// only last log is taken into account
|
||||
@@ -296,7 +290,7 @@ impl ValidatorSet for ValidatorSafeContract {
|
||||
}
|
||||
|
||||
fn on_epoch_begin(&self, _first: bool, _header: &Header, caller: &mut SystemCall) -> Result<(), ::error::Error> {
|
||||
let data = self.provider.functions().finalize_change().input();
|
||||
let data = validator_set::functions::finalize_change::encode_input();
|
||||
caller(self.contract_address, data)
|
||||
.map(|_| ())
|
||||
.map_err(::engines::EngineError::FailedSystemCall)
|
||||
@@ -304,7 +298,7 @@ impl ValidatorSet for ValidatorSafeContract {
|
||||
}
|
||||
|
||||
fn genesis_epoch_data(&self, header: &Header, call: &Call) -> Result<Vec<u8>, String> {
|
||||
prove_initial(&self.provider, self.contract_address, header, call)
|
||||
prove_initial(self.contract_address, header, call)
|
||||
}
|
||||
|
||||
fn is_epoch_end(&self, _first: bool, _chain_head: &Header) -> Option<Vec<u8>> {
|
||||
@@ -322,7 +316,6 @@ impl ValidatorSet for ValidatorSafeContract {
|
||||
let state_proof = Arc::new(StateProof {
|
||||
contract_address: self.contract_address,
|
||||
header: header.clone(),
|
||||
provider: validator_set::ValidatorSet::default(),
|
||||
});
|
||||
return ::engines::EpochChange::Yes(::engines::Proof::WithState(state_proof as Arc<_>));
|
||||
}
|
||||
@@ -361,7 +354,7 @@ impl ValidatorSet for ValidatorSafeContract {
|
||||
let (old_header, state_items) = decode_first_proof(&rlp)?;
|
||||
let number = old_header.number();
|
||||
let old_hash = old_header.hash();
|
||||
let addresses = check_first_proof(machine, &self.provider, self.contract_address, old_header, &state_items)
|
||||
let addresses = check_first_proof(machine, self.contract_address, old_header, &state_items)
|
||||
.map_err(::engines::EngineError::InsufficientProof)?;
|
||||
|
||||
trace!(target: "engine", "extracted epoch set at #{}: {} addresses",
|
||||
|
||||
@@ -34,12 +34,18 @@ pub struct TestSet {
|
||||
last_benign: Arc<AtomicUsize>,
|
||||
}
|
||||
|
||||
impl Default for TestSet {
|
||||
fn default() -> Self {
|
||||
TestSet::new(Default::default(), Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl TestSet {
|
||||
pub fn new(last_malicious: Arc<AtomicUsize>, last_benign: Arc<AtomicUsize>) -> Self {
|
||||
TestSet {
|
||||
validator: SimpleList::new(vec![Address::from_str("7d577a597b2742b498cb5cf0c26cdcd726d39e6e").unwrap()]),
|
||||
last_malicious: last_malicious,
|
||||
last_benign: last_benign,
|
||||
last_malicious,
|
||||
last_benign,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ use engines::EngineError;
|
||||
use ethkey::Error as EthkeyError;
|
||||
use account_provider::SignError as AccountsError;
|
||||
use transaction::Error as TransactionError;
|
||||
use rlp;
|
||||
|
||||
pub use executed::{ExecutionError, CallError};
|
||||
|
||||
@@ -88,6 +89,8 @@ pub enum BlockError {
|
||||
InvalidNumber(Mismatch<BlockNumber>),
|
||||
/// Block number isn't sensible.
|
||||
RidiculousNumber(OutOfBounds<BlockNumber>),
|
||||
/// Timestamp header overflowed
|
||||
TimestampOverflow,
|
||||
/// Too many transactions from a particular address.
|
||||
TooManyTransactions(Address),
|
||||
/// Parent given is unknown.
|
||||
@@ -137,6 +140,7 @@ impl fmt::Display for BlockError {
|
||||
UnknownParent(ref hash) => format!("Unknown parent: {}", hash),
|
||||
UnknownUncleParent(ref hash) => format!("Unknown uncle parent: {}", hash),
|
||||
UnknownEpochTransition(ref num) => format!("Unknown transition to epoch number: {}", num),
|
||||
TimestampOverflow => format!("Timestamp overflow"),
|
||||
TooManyTransactions(ref address) => format!("Too many transactions from: {}", address),
|
||||
};
|
||||
|
||||
@@ -194,40 +198,6 @@ error_chain! {
|
||||
}
|
||||
}
|
||||
|
||||
error_chain! {
|
||||
types {
|
||||
BlockImportError, BlockImportErrorKind, BlockImportErrorResultExt;
|
||||
}
|
||||
|
||||
links {
|
||||
Import(ImportError, ImportErrorKind) #[doc = "Import error"];
|
||||
Queue(QueueError, QueueErrorKind) #[doc = "Io channel queue error"];
|
||||
}
|
||||
|
||||
foreign_links {
|
||||
Block(BlockError) #[doc = "Block error"];
|
||||
Decoder(::rlp::DecoderError) #[doc = "Rlp decoding error"];
|
||||
}
|
||||
|
||||
errors {
|
||||
#[doc = "Other error"]
|
||||
Other(err: String) {
|
||||
description("Other error")
|
||||
display("Other error {}", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Error> for BlockImportError {
|
||||
fn from(e: Error) -> Self {
|
||||
match e {
|
||||
Error(ErrorKind::Block(block_error), _) => BlockImportErrorKind::Block(block_error).into(),
|
||||
Error(ErrorKind::Import(import_error), _) => BlockImportErrorKind::Import(import_error.into()).into(),
|
||||
_ => BlockImportErrorKind::Other(format!("other block import error: {:?}", e)).into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Api-level error for transaction import
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum TransactionImportError {
|
||||
@@ -253,6 +223,7 @@ error_chain! {
|
||||
|
||||
links {
|
||||
Import(ImportError, ImportErrorKind) #[doc = "Error concerning block import." ];
|
||||
Queue(QueueError, QueueErrorKind) #[doc = "Io channel queue error"];
|
||||
}
|
||||
|
||||
foreign_links {
|
||||
@@ -265,6 +236,7 @@ error_chain! {
|
||||
Snappy(InvalidInput) #[doc = "Snappy error."];
|
||||
Engine(EngineError) #[doc = "Consensus vote error."];
|
||||
Ethkey(EthkeyError) #[doc = "Ethkey error."];
|
||||
Decoder(rlp::DecoderError) #[doc = "RLP decoding errors"];
|
||||
}
|
||||
|
||||
errors {
|
||||
@@ -297,40 +269,15 @@ error_chain! {
|
||||
description("Unknown engine name")
|
||||
display("Unknown engine name ({})", name)
|
||||
}
|
||||
|
||||
#[doc = "RLP decoding errors"]
|
||||
Decoder(err: ::rlp::DecoderError) {
|
||||
description("decoding value failed")
|
||||
display("decoding value failed with error: {}", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Result of import block operation.
|
||||
pub type ImportResult = EthcoreResult<H256>;
|
||||
|
||||
impl From<AccountsError> for Error {
|
||||
fn from(err: AccountsError) -> Error {
|
||||
ErrorKind::AccountProvider(err).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<::rlp::DecoderError> for Error {
|
||||
fn from(err: ::rlp::DecoderError) -> Error {
|
||||
ErrorKind::Decoder(err).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BlockImportError> for Error {
|
||||
fn from(err: BlockImportError) -> Error {
|
||||
match err {
|
||||
BlockImportError(BlockImportErrorKind::Block(e), _) => ErrorKind::Block(e).into(),
|
||||
BlockImportError(BlockImportErrorKind::Import(e), _) => ErrorKind::Import(e).into(),
|
||||
_ => ErrorKind::Msg(format!("other block import error: {:?}", err)).into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SnapshotError> for Error {
|
||||
fn from(err: SnapshotError) -> Error {
|
||||
match err {
|
||||
|
||||
@@ -21,7 +21,7 @@ use std::sync::Arc;
|
||||
use hash::{KECCAK_EMPTY_LIST_RLP};
|
||||
use engines::block_reward::{self, BlockRewardContract, RewardKind};
|
||||
use ethash::{self, quick_get_difficulty, slow_hash_block_number, EthashManager, OptimizeFor};
|
||||
use ethereum_types::{H256, H64, U256, Address};
|
||||
use ethereum_types::{H256, H64, U256};
|
||||
use unexpected::{OutOfBounds, Mismatch};
|
||||
use block::*;
|
||||
use error::{BlockError, Error};
|
||||
@@ -98,18 +98,6 @@ pub struct EthashParams {
|
||||
pub ecip1010_continue_transition: u64,
|
||||
/// Total block number for one ECIP-1017 era.
|
||||
pub ecip1017_era_rounds: u64,
|
||||
/// Number of first block where MCIP-3 begins.
|
||||
pub mcip3_transition: u64,
|
||||
/// MCIP-3 Block reward coin-base for miners.
|
||||
pub mcip3_miner_reward: U256,
|
||||
/// MCIP-3 Block reward ubi-base for basic income.
|
||||
pub mcip3_ubi_reward: U256,
|
||||
/// MCIP-3 contract address for universal basic income.
|
||||
pub mcip3_ubi_contract: Address,
|
||||
/// MCIP-3 Block reward dev-base for dev funds.
|
||||
pub mcip3_dev_reward: U256,
|
||||
/// MCIP-3 contract address for the developer funds.
|
||||
pub mcip3_dev_contract: Address,
|
||||
/// Block reward in base units.
|
||||
pub block_reward: BTreeMap<BlockNumber, U256>,
|
||||
/// EXPIP-2 block height
|
||||
@@ -140,12 +128,6 @@ impl From<ethjson::spec::EthashParams> for EthashParams {
|
||||
ecip1010_pause_transition: p.ecip1010_pause_transition.map_or(u64::max_value(), Into::into),
|
||||
ecip1010_continue_transition: p.ecip1010_continue_transition.map_or(u64::max_value(), Into::into),
|
||||
ecip1017_era_rounds: p.ecip1017_era_rounds.map_or(u64::max_value(), Into::into),
|
||||
mcip3_transition: p.mcip3_transition.map_or(u64::max_value(), Into::into),
|
||||
mcip3_miner_reward: p.mcip3_miner_reward.map_or_else(Default::default, Into::into),
|
||||
mcip3_ubi_reward: p.mcip3_ubi_reward.map_or(U256::from(0), Into::into),
|
||||
mcip3_ubi_contract: p.mcip3_ubi_contract.map_or_else(Address::new, Into::into),
|
||||
mcip3_dev_reward: p.mcip3_dev_reward.map_or(U256::from(0), Into::into),
|
||||
mcip3_dev_contract: p.mcip3_dev_contract.map_or_else(Address::new, Into::into),
|
||||
block_reward: p.block_reward.map_or_else(
|
||||
|| {
|
||||
let mut ret = BTreeMap::new();
|
||||
@@ -240,6 +222,8 @@ impl Engine<EthereumMachine> for Arc<Ethash> {
|
||||
|
||||
fn maximum_uncle_count(&self, _block: BlockNumber) -> usize { 2 }
|
||||
|
||||
fn maximum_gas_limit(&self) -> Option<U256> { Some(0x7fff_ffff_ffff_ffffu64.into()) }
|
||||
|
||||
fn populate_from_parent(&self, header: &mut Header, parent: &Header) {
|
||||
let difficulty = self.calculate_difficulty(header, parent);
|
||||
header.set_difficulty(difficulty);
|
||||
@@ -287,21 +271,7 @@ impl Engine<EthereumMachine> for Arc<Ethash> {
|
||||
// Bestow block rewards.
|
||||
let mut result_block_reward = reward + reward.shr(5) * U256::from(n_uncles);
|
||||
|
||||
if number >= self.ethash_params.mcip3_transition {
|
||||
result_block_reward = self.ethash_params.mcip3_miner_reward;
|
||||
|
||||
let ubi_contract = self.ethash_params.mcip3_ubi_contract;
|
||||
let ubi_reward = self.ethash_params.mcip3_ubi_reward;
|
||||
let dev_contract = self.ethash_params.mcip3_dev_contract;
|
||||
let dev_reward = self.ethash_params.mcip3_dev_reward;
|
||||
|
||||
rewards.push((author, RewardKind::Author, result_block_reward));
|
||||
rewards.push((ubi_contract, RewardKind::External, ubi_reward));
|
||||
rewards.push((dev_contract, RewardKind::External, dev_reward));
|
||||
|
||||
} else {
|
||||
rewards.push((author, RewardKind::Author, result_block_reward));
|
||||
}
|
||||
rewards.push((author, RewardKind::Author, result_block_reward));
|
||||
|
||||
// Bestow uncle rewards.
|
||||
for u in LiveBlock::uncles(&*block) {
|
||||
@@ -354,10 +324,6 @@ impl Engine<EthereumMachine> for Arc<Ethash> {
|
||||
return Err(From::from(BlockError::InvalidProofOfWork(OutOfBounds { min: Some(header.difficulty().clone()), max: None, found: difficulty })));
|
||||
}
|
||||
|
||||
if header.gas_limit() > &0x7fffffffffffffffu64.into() {
|
||||
return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds { min: None, max: Some(0x7fffffffffffffffu64.into()), found: header.gas_limit().clone() })));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -549,12 +515,6 @@ mod tests {
|
||||
ecip1010_pause_transition: u64::max_value(),
|
||||
ecip1010_continue_transition: u64::max_value(),
|
||||
ecip1017_era_rounds: u64::max_value(),
|
||||
mcip3_transition: u64::max_value(),
|
||||
mcip3_miner_reward: 0.into(),
|
||||
mcip3_ubi_reward: 0.into(),
|
||||
mcip3_ubi_contract: "0000000000000000000000000000000000000001".into(),
|
||||
mcip3_dev_reward: 0.into(),
|
||||
mcip3_dev_contract: "0000000000000000000000000000000000000001".into(),
|
||||
expip2_transition: u64::max_value(),
|
||||
expip2_duration_limit: 30,
|
||||
block_reward_contract: None,
|
||||
@@ -681,7 +641,7 @@ mod tests {
|
||||
fn can_do_difficulty_verification_fail() {
|
||||
let engine = test_spec().engine;
|
||||
let mut header: Header = Header::default();
|
||||
header.set_seal(vec![rlp::encode(&H256::zero()).into_vec(), rlp::encode(&H64::zero()).into_vec()]);
|
||||
header.set_seal(vec![rlp::encode(&H256::zero()), rlp::encode(&H64::zero())]);
|
||||
|
||||
let verify_result = engine.verify_block_basic(&header);
|
||||
|
||||
@@ -696,7 +656,7 @@ mod tests {
|
||||
fn can_do_proof_of_work_verification_fail() {
|
||||
let engine = test_spec().engine;
|
||||
let mut header: Header = Header::default();
|
||||
header.set_seal(vec![rlp::encode(&H256::zero()).into_vec(), rlp::encode(&H64::zero()).into_vec()]);
|
||||
header.set_seal(vec![rlp::encode(&H256::zero()), rlp::encode(&H64::zero())]);
|
||||
header.set_difficulty(U256::from_str("ffffffffffffffffffffffffffffffffffffffffffffaaaaaaaaaaaaaaaaaaaa").unwrap());
|
||||
|
||||
let verify_result = engine.verify_block_basic(&header);
|
||||
@@ -737,7 +697,7 @@ mod tests {
|
||||
fn can_do_seal256_verification_fail() {
|
||||
let engine = test_spec().engine;
|
||||
let mut header: Header = Header::default();
|
||||
header.set_seal(vec![rlp::encode(&H256::zero()).into_vec(), rlp::encode(&H64::zero()).into_vec()]);
|
||||
header.set_seal(vec![rlp::encode(&H256::zero()), rlp::encode(&H64::zero())]);
|
||||
let verify_result = engine.verify_block_unordered(&header);
|
||||
|
||||
match verify_result {
|
||||
@@ -751,7 +711,7 @@ mod tests {
|
||||
fn can_do_proof_of_work_unordered_verification_fail() {
|
||||
let engine = test_spec().engine;
|
||||
let mut header: Header = Header::default();
|
||||
header.set_seal(vec![rlp::encode(&H256::from("b251bd2e0283d0658f2cadfdc8ca619b5de94eca5742725e2e757dd13ed7503d")).into_vec(), rlp::encode(&H64::zero()).into_vec()]);
|
||||
header.set_seal(vec![rlp::encode(&H256::from("b251bd2e0283d0658f2cadfdc8ca619b5de94eca5742725e2e757dd13ed7503d")), rlp::encode(&H64::zero())]);
|
||||
header.set_difficulty(U256::from_str("ffffffffffffffffffffffffffffffffffffffffffffaaaaaaaaaaaaaaaaaaaa").unwrap());
|
||||
|
||||
let verify_result = engine.verify_block_unordered(&header);
|
||||
@@ -944,7 +904,7 @@ mod tests {
|
||||
let tempdir = TempDir::new("").unwrap();
|
||||
let ethash = Ethash::new(tempdir.path(), ethparams, machine, None);
|
||||
let mut header = Header::default();
|
||||
header.set_seal(vec![rlp::encode(&H256::from("b251bd2e0283d0658f2cadfdc8ca619b5de94eca5742725e2e757dd13ed7503d")).into_vec(), rlp::encode(&H64::zero()).into_vec()]);
|
||||
header.set_seal(vec![rlp::encode(&H256::from("b251bd2e0283d0658f2cadfdc8ca619b5de94eca5742725e2e757dd13ed7503d")), rlp::encode(&H64::zero())]);
|
||||
let info = ethash.extra_info(&header);
|
||||
assert_eq!(info["nonce"], "0x0000000000000000");
|
||||
assert_eq!(info["mixHash"], "0xb251bd2e0283d0658f2cadfdc8ca619b5de94eca5742725e2e757dd13ed7503d");
|
||||
|
||||
@@ -69,6 +69,8 @@ pub fn new_expanse<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
|
||||
|
||||
/// Create a new Musicoin mainnet chain spec.
|
||||
pub fn new_musicoin<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
|
||||
// The musicoin chain spec uses a block reward contract which can be found at
|
||||
// https://gist.github.com/andresilva/6f2afaf9486732a0797f4bdeae018ee9
|
||||
load(params.into(), include_bytes!("../../res/ethereum/musicoin.json"))
|
||||
}
|
||||
|
||||
@@ -87,11 +89,6 @@ pub fn new_social<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
|
||||
load(params.into(), include_bytes!("../../res/ethereum/social.json"))
|
||||
}
|
||||
|
||||
/// Create a new Olympic testnet chain spec.
|
||||
pub fn new_olympic<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
|
||||
load(params.into(), include_bytes!("../../res/ethereum/olympic.json"))
|
||||
}
|
||||
|
||||
/// Create a new Morden testnet chain spec.
|
||||
pub fn new_morden<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
|
||||
load(params.into(), include_bytes!("../../res/ethereum/morden.json"))
|
||||
@@ -112,6 +109,11 @@ pub fn new_sokol<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
|
||||
load(params.into(), include_bytes!("../../res/ethereum/poasokol.json"))
|
||||
}
|
||||
|
||||
/// Create a new Callisto chaun spec
|
||||
pub fn new_callisto<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
|
||||
load(params.into(), include_bytes!("../../res/ethereum/callisto.json"))
|
||||
}
|
||||
|
||||
// For tests
|
||||
|
||||
/// Create a new Foundation Frontier-era chain spec as though it never changes to Homestead.
|
||||
@@ -141,6 +143,9 @@ pub fn new_byzantium_test() -> Spec { load(None, include_bytes!("../../res/ether
|
||||
/// Create a new Foundation Constantinople era spec.
|
||||
pub fn new_constantinople_test() -> Spec { load(None, include_bytes!("../../res/ethereum/constantinople_test.json")) }
|
||||
|
||||
/// Create a new Foundation St. Peter's (Contantinople Fix) era spec.
|
||||
pub fn new_constantinople_fix_test() -> Spec { load(None, include_bytes!("../../res/ethereum/st_peters_test.json")) }
|
||||
|
||||
/// Create a new Musicoin-MCIP3-era spec.
|
||||
pub fn new_mcip3_test() -> Spec { load(None, include_bytes!("../../res/ethereum/mcip3_test.json")) }
|
||||
|
||||
@@ -152,12 +157,18 @@ pub fn new_frontier_test_machine() -> EthereumMachine { load_machine(include_byt
|
||||
/// Create a new Foundation Homestead-era chain spec as though it never changed from Frontier.
|
||||
pub fn new_homestead_test_machine() -> EthereumMachine { load_machine(include_bytes!("../../res/ethereum/homestead_test.json")) }
|
||||
|
||||
/// Create a new Foundation Homestead-EIP210-era chain spec as though it never changed from Homestead/Frontier.
|
||||
pub fn new_eip210_test_machine() -> EthereumMachine { load_machine(include_bytes!("../../res/ethereum/eip210_test.json")) }
|
||||
|
||||
/// Create a new Foundation Byzantium era spec.
|
||||
pub fn new_byzantium_test_machine() -> EthereumMachine { load_machine(include_bytes!("../../res/ethereum/byzantium_test.json")) }
|
||||
|
||||
/// Create a new Foundation Constantinople era spec.
|
||||
pub fn new_constantinople_test_machine() -> EthereumMachine { load_machine(include_bytes!("../../res/ethereum/constantinople_test.json")) }
|
||||
|
||||
/// Create a new Foundation St. Peter's (Contantinople Fix) era spec.
|
||||
pub fn new_constantinople_fix_test_machine() -> EthereumMachine { load_machine(include_bytes!("../../res/ethereum/st_peters_test.json")) }
|
||||
|
||||
/// Create a new Musicoin-MCIP3-era spec.
|
||||
pub fn new_mcip3_test_machine() -> EthereumMachine { load_machine(include_bytes!("../../res/ethereum/mcip3_test.json")) }
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,9 +25,8 @@ use executive::*;
|
||||
use vm::{
|
||||
self, ActionParams, ActionValue, EnvInfo, CallType, Schedule,
|
||||
Ext, ContractCreateResult, MessageCallResult, CreateContractAddress,
|
||||
ReturnData
|
||||
ReturnData, TrapKind
|
||||
};
|
||||
use evm::FinalizationResult;
|
||||
use transaction::UNSIGNED_SENDER;
|
||||
use trace::{Tracer, VMTracer};
|
||||
|
||||
@@ -67,7 +66,8 @@ pub struct Externalities<'a, T: 'a, V: 'a, B: 'a> {
|
||||
state: &'a mut State<B>,
|
||||
env_info: &'a EnvInfo,
|
||||
depth: usize,
|
||||
origin_info: OriginInfo,
|
||||
stack_depth: usize,
|
||||
origin_info: &'a OriginInfo,
|
||||
substate: &'a mut Substate,
|
||||
machine: &'a Machine,
|
||||
schedule: &'a Schedule,
|
||||
@@ -87,7 +87,8 @@ impl<'a, T: 'a, V: 'a, B: 'a> Externalities<'a, T, V, B>
|
||||
machine: &'a Machine,
|
||||
schedule: &'a Schedule,
|
||||
depth: usize,
|
||||
origin_info: OriginInfo,
|
||||
stack_depth: usize,
|
||||
origin_info: &'a OriginInfo,
|
||||
substate: &'a mut Substate,
|
||||
output: OutputPolicy,
|
||||
tracer: &'a mut T,
|
||||
@@ -98,6 +99,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Externalities<'a, T, V, B>
|
||||
state: state,
|
||||
env_info: env_info,
|
||||
depth: depth,
|
||||
stack_depth: stack_depth,
|
||||
origin_info: origin_info,
|
||||
substate: substate,
|
||||
machine: machine,
|
||||
@@ -114,7 +116,12 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
||||
where T: Tracer, V: VMTracer, B: StateBackend
|
||||
{
|
||||
fn initial_storage_at(&self, key: &H256) -> vm::Result<H256> {
|
||||
self.state.checkpoint_storage_at(0, &self.origin_info.address, key).map(|v| v.unwrap_or(H256::zero())).map_err(Into::into)
|
||||
if self.state.is_base_storage_root_unchanged(&self.origin_info.address)? {
|
||||
self.state.checkpoint_storage_at(0, &self.origin_info.address, key).map(|v| v.unwrap_or(H256::zero())).map_err(Into::into)
|
||||
} else {
|
||||
warn!(target: "externalities", "Detected existing account {:#x} where a forced contract creation happened.", self.origin_info.address);
|
||||
Ok(H256::zero())
|
||||
}
|
||||
}
|
||||
|
||||
fn storage_at(&self, key: &H256) -> vm::Result<H256> {
|
||||
@@ -176,7 +183,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
||||
};
|
||||
|
||||
let mut ex = Executive::new(self.state, self.env_info, self.machine, self.schedule);
|
||||
let r = ex.call(params, self.substate, self.tracer, self.vm_tracer);
|
||||
let r = ex.call_with_crossbeam(params, self.substate, self.stack_depth + 1, self.tracer, self.vm_tracer);
|
||||
let output = match &r {
|
||||
Ok(ref r) => H256::from(&r.return_data[..32]),
|
||||
_ => H256::new(),
|
||||
@@ -206,14 +213,15 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
||||
gas: &U256,
|
||||
value: &U256,
|
||||
code: &[u8],
|
||||
address_scheme: CreateContractAddress
|
||||
) -> ContractCreateResult {
|
||||
address_scheme: CreateContractAddress,
|
||||
trap: bool,
|
||||
) -> ::std::result::Result<ContractCreateResult, TrapKind> {
|
||||
// create new contract address
|
||||
let (address, code_hash) = match self.state.nonce(&self.origin_info.address) {
|
||||
Ok(nonce) => contract_address(address_scheme, &self.origin_info.address, &nonce, &code),
|
||||
Err(e) => {
|
||||
debug!(target: "ext", "Database corruption encountered: {:?}", e);
|
||||
return ContractCreateResult::Failed
|
||||
return Ok(ContractCreateResult::Failed)
|
||||
}
|
||||
};
|
||||
|
||||
@@ -237,23 +245,19 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
||||
if !self.schedule.keep_unsigned_nonce || params.sender != UNSIGNED_SENDER {
|
||||
if let Err(e) = self.state.inc_nonce(&self.origin_info.address) {
|
||||
debug!(target: "ext", "Database corruption encountered: {:?}", e);
|
||||
return ContractCreateResult::Failed
|
||||
return Ok(ContractCreateResult::Failed)
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut ex = Executive::from_parent(self.state, self.env_info, self.machine, self.schedule, self.depth, self.static_flag);
|
||||
|
||||
if trap {
|
||||
return Err(TrapKind::Create(params, address));
|
||||
}
|
||||
|
||||
// TODO: handle internal error separately
|
||||
match ex.create(params, self.substate, self.tracer, self.vm_tracer) {
|
||||
Ok(FinalizationResult{ gas_left, apply_state: true, .. }) => {
|
||||
self.substate.contracts_created.push(address.clone());
|
||||
ContractCreateResult::Created(address, gas_left)
|
||||
},
|
||||
Ok(FinalizationResult{ gas_left, apply_state: false, return_data }) => {
|
||||
ContractCreateResult::Reverted(gas_left, return_data)
|
||||
},
|
||||
_ => ContractCreateResult::Failed,
|
||||
}
|
||||
let mut ex = Executive::from_parent(self.state, self.env_info, self.machine, self.schedule, self.depth, self.static_flag);
|
||||
let out = ex.create_with_crossbeam(params, self.substate, self.stack_depth + 1, self.tracer, self.vm_tracer);
|
||||
Ok(into_contract_create_result(out, &address, self.substate))
|
||||
}
|
||||
|
||||
fn call(
|
||||
@@ -264,8 +268,9 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
||||
value: Option<U256>,
|
||||
data: &[u8],
|
||||
code_address: &Address,
|
||||
call_type: CallType
|
||||
) -> MessageCallResult {
|
||||
call_type: CallType,
|
||||
trap: bool,
|
||||
) -> ::std::result::Result<MessageCallResult, TrapKind> {
|
||||
trace!(target: "externalities", "call");
|
||||
|
||||
let code_res = self.state.code(code_address)
|
||||
@@ -273,7 +278,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
||||
|
||||
let (code, code_hash) = match code_res {
|
||||
Ok((code, hash)) => (code, hash),
|
||||
Err(_) => return MessageCallResult::Failed,
|
||||
Err(_) => return Ok(MessageCallResult::Failed),
|
||||
};
|
||||
|
||||
let mut params = ActionParams {
|
||||
@@ -295,13 +300,13 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
||||
params.value = ActionValue::Transfer(value);
|
||||
}
|
||||
|
||||
let mut ex = Executive::from_parent(self.state, self.env_info, self.machine, self.schedule, self.depth, self.static_flag);
|
||||
|
||||
match ex.call(params, self.substate, self.tracer, self.vm_tracer) {
|
||||
Ok(FinalizationResult{ gas_left, return_data, apply_state: true }) => MessageCallResult::Success(gas_left, return_data),
|
||||
Ok(FinalizationResult{ gas_left, return_data, apply_state: false }) => MessageCallResult::Reverted(gas_left, return_data),
|
||||
_ => MessageCallResult::Failed
|
||||
if trap {
|
||||
return Err(TrapKind::Call(params));
|
||||
}
|
||||
|
||||
let mut ex = Executive::from_parent(self.state, self.env_info, self.machine, self.schedule, self.depth, self.static_flag);
|
||||
let out = ex.call_with_crossbeam(params, self.substate, self.stack_depth + 1, self.tracer, self.vm_tracer);
|
||||
Ok(into_message_call_result(out))
|
||||
}
|
||||
|
||||
fn extcode(&self, address: &Address) -> vm::Result<Option<Arc<Bytes>>> {
|
||||
@@ -394,24 +399,24 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
||||
self.depth
|
||||
}
|
||||
|
||||
fn add_sstore_refund(&mut self, value: U256) {
|
||||
self.substate.sstore_clears_refund = self.substate.sstore_clears_refund.saturating_add(value);
|
||||
fn add_sstore_refund(&mut self, value: usize) {
|
||||
self.substate.sstore_clears_refund += value as i128;
|
||||
}
|
||||
|
||||
fn sub_sstore_refund(&mut self, value: U256) {
|
||||
self.substate.sstore_clears_refund = self.substate.sstore_clears_refund.saturating_sub(value);
|
||||
fn sub_sstore_refund(&mut self, value: usize) {
|
||||
self.substate.sstore_clears_refund -= value as i128;
|
||||
}
|
||||
|
||||
fn trace_next_instruction(&mut self, pc: usize, instruction: u8, current_gas: U256) -> bool {
|
||||
self.vm_tracer.trace_next_instruction(pc, instruction, current_gas)
|
||||
}
|
||||
|
||||
fn trace_prepare_execute(&mut self, pc: usize, instruction: u8, gas_cost: U256) {
|
||||
self.vm_tracer.trace_prepare_execute(pc, instruction, gas_cost)
|
||||
fn trace_prepare_execute(&mut self, pc: usize, instruction: u8, gas_cost: U256, mem_written: Option<(usize, usize)>, store_written: Option<(U256, U256)>) {
|
||||
self.vm_tracer.trace_prepare_execute(pc, instruction, gas_cost, mem_written, store_written)
|
||||
}
|
||||
|
||||
fn trace_executed(&mut self, gas_used: U256, stack_push: &[U256], mem_diff: Option<(usize, &[u8])>, store_diff: Option<(U256, U256)>) {
|
||||
self.vm_tracer.trace_executed(gas_used, stack_push, mem_diff, store_diff)
|
||||
fn trace_executed(&mut self, gas_used: U256, stack_push: &[U256], mem: &[u8]) {
|
||||
self.vm_tracer.trace_executed(gas_used, stack_push, mem)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -480,8 +485,9 @@ mod tests {
|
||||
let state = &mut setup.state;
|
||||
let mut tracer = NoopTracer;
|
||||
let mut vm_tracer = NoopVMTracer;
|
||||
let origin_info = get_test_origin();
|
||||
|
||||
let ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||
let ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, 0, &origin_info, &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||
|
||||
assert_eq!(ext.env_info().number, 100);
|
||||
}
|
||||
@@ -492,8 +498,9 @@ mod tests {
|
||||
let state = &mut setup.state;
|
||||
let mut tracer = NoopTracer;
|
||||
let mut vm_tracer = NoopVMTracer;
|
||||
let origin_info = get_test_origin();
|
||||
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, 0, &origin_info, &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||
|
||||
let hash = ext.blockhash(&"0000000000000000000000000000000000000000000000000000000000120000".parse::<U256>().unwrap());
|
||||
|
||||
@@ -516,8 +523,9 @@ mod tests {
|
||||
let state = &mut setup.state;
|
||||
let mut tracer = NoopTracer;
|
||||
let mut vm_tracer = NoopVMTracer;
|
||||
let origin_info = get_test_origin();
|
||||
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, 0, &origin_info, &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||
|
||||
let hash = ext.blockhash(&"0000000000000000000000000000000000000000000000000000000000120000".parse::<U256>().unwrap());
|
||||
|
||||
@@ -531,8 +539,9 @@ mod tests {
|
||||
let state = &mut setup.state;
|
||||
let mut tracer = NoopTracer;
|
||||
let mut vm_tracer = NoopVMTracer;
|
||||
let origin_info = get_test_origin();
|
||||
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, 0, &origin_info, &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||
|
||||
// this should panic because we have no balance on any account
|
||||
ext.call(
|
||||
@@ -542,8 +551,9 @@ mod tests {
|
||||
Some("0000000000000000000000000000000000000000000000000000000000150000".parse::<U256>().unwrap()),
|
||||
&[],
|
||||
&Address::new(),
|
||||
CallType::Call
|
||||
);
|
||||
CallType::Call,
|
||||
false,
|
||||
).ok().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -555,9 +565,10 @@ mod tests {
|
||||
let state = &mut setup.state;
|
||||
let mut tracer = NoopTracer;
|
||||
let mut vm_tracer = NoopVMTracer;
|
||||
let origin_info = get_test_origin();
|
||||
|
||||
{
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, 0, &origin_info, &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||
ext.log(log_topics, &log_data).unwrap();
|
||||
}
|
||||
|
||||
@@ -572,9 +583,10 @@ mod tests {
|
||||
let state = &mut setup.state;
|
||||
let mut tracer = NoopTracer;
|
||||
let mut vm_tracer = NoopVMTracer;
|
||||
let origin_info = get_test_origin();
|
||||
|
||||
{
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, 0, &origin_info, &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||
ext.suicide(refund_account).unwrap();
|
||||
}
|
||||
|
||||
@@ -589,11 +601,12 @@ mod tests {
|
||||
let state = &mut setup.state;
|
||||
let mut tracer = NoopTracer;
|
||||
let mut vm_tracer = NoopVMTracer;
|
||||
let origin_info = get_test_origin();
|
||||
|
||||
let address = {
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||
match ext.create(&U256::max_value(), &U256::zero(), &[], CreateContractAddress::FromSenderAndNonce) {
|
||||
ContractCreateResult::Created(address, _) => address,
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, 0, &origin_info, &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||
match ext.create(&U256::max_value(), &U256::zero(), &[], CreateContractAddress::FromSenderAndNonce, false) {
|
||||
Ok(ContractCreateResult::Created(address, _)) => address,
|
||||
_ => panic!("Test create failed; expected Created, got Failed/Reverted."),
|
||||
}
|
||||
};
|
||||
@@ -609,12 +622,13 @@ mod tests {
|
||||
let state = &mut setup.state;
|
||||
let mut tracer = NoopTracer;
|
||||
let mut vm_tracer = NoopVMTracer;
|
||||
let origin_info = get_test_origin();
|
||||
|
||||
let address = {
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, 0, &origin_info, &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||
|
||||
match ext.create(&U256::max_value(), &U256::zero(), &[], CreateContractAddress::FromSenderSaltAndCodeHash(H256::default())) {
|
||||
ContractCreateResult::Created(address, _) => address,
|
||||
match ext.create(&U256::max_value(), &U256::zero(), &[], CreateContractAddress::FromSenderSaltAndCodeHash(H256::default()), false) {
|
||||
Ok(ContractCreateResult::Created(address, _)) => address,
|
||||
_ => panic!("Test create failed; expected Created, got Failed/Reverted."),
|
||||
}
|
||||
};
|
||||
|
||||
@@ -18,7 +18,7 @@ use trie::TrieFactory;
|
||||
use ethtrie::RlpCodec;
|
||||
use account_db::Factory as AccountFactory;
|
||||
use evm::{Factory as EvmFactory, VMType};
|
||||
use vm::{Vm, ActionParams, Schedule};
|
||||
use vm::{Exec, ActionParams, Schedule};
|
||||
use wasm::WasmInterpreter;
|
||||
use keccak_hasher::KeccakHasher;
|
||||
|
||||
@@ -31,7 +31,7 @@ pub struct VmFactory {
|
||||
}
|
||||
|
||||
impl VmFactory {
|
||||
pub fn create(&self, params: ActionParams, schedule: &Schedule, depth: usize) -> Box<Vm> {
|
||||
pub fn create(&self, params: ActionParams, schedule: &Schedule, depth: usize) -> Box<Exec> {
|
||||
if schedule.wasm.is_some() && params.code.as_ref().map_or(false, |code| code.len() > 4 && &code[0..4] == WASM_MAGIC_NUMBER) {
|
||||
Box::new(WasmInterpreter::new(params))
|
||||
} else {
|
||||
|
||||
@@ -449,7 +449,7 @@ mod tests {
|
||||
let header_rlp = "f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23".from_hex().unwrap();
|
||||
|
||||
let header: Header = rlp::decode(&header_rlp).expect("error decoding header");
|
||||
let encoded_header = rlp::encode(&header).into_vec();
|
||||
let encoded_header = rlp::encode(&header);
|
||||
|
||||
assert_eq!(header_rlp, encoded_header);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,8 @@ use miner::Miner;
|
||||
use io::IoChannel;
|
||||
use test_helpers;
|
||||
use verification::queue::kind::blocks::Unverified;
|
||||
|
||||
use verification::VerifierType;
|
||||
use super::SKIP_TEST_STATE;
|
||||
use super::HookType;
|
||||
|
||||
/// Run chain jsontests on a given folder.
|
||||
@@ -36,12 +37,20 @@ pub fn run_test_file<H: FnMut(&str, HookType)>(p: &Path, h: &mut H) {
|
||||
::json_tests::test_common::run_test_file(p, json_chain_test, h)
|
||||
}
|
||||
|
||||
fn skip_test(name: &String) -> bool {
|
||||
SKIP_TEST_STATE.block.iter().any(|block_test|block_test.subtests.contains(name))
|
||||
}
|
||||
|
||||
pub fn json_chain_test<H: FnMut(&str, HookType)>(json_data: &[u8], start_stop_hook: &mut H) -> Vec<String> {
|
||||
::ethcore_logger::init_log();
|
||||
let tests = ethjson::blockchain::Test::load(json_data).unwrap();
|
||||
let mut failed = Vec::new();
|
||||
|
||||
for (name, blockchain) in tests.into_iter() {
|
||||
if skip_test(&name) {
|
||||
println!(" - {} | {:?} Ignoring tests because in skip list", name, blockchain.network);
|
||||
continue;
|
||||
}
|
||||
start_stop_hook(&name, HookType::OnStart);
|
||||
|
||||
let mut fail = false;
|
||||
@@ -75,6 +84,10 @@ pub fn json_chain_test<H: FnMut(&str, HookType)>(json_data: &[u8], start_stop_ho
|
||||
{
|
||||
let db = test_helpers::new_db();
|
||||
let mut config = ClientConfig::default();
|
||||
if ethjson::blockchain::Engine::NoProof == blockchain.engine {
|
||||
config.verifier_type = VerifierType::CanonNoSeal;
|
||||
config.check_seal = false;
|
||||
}
|
||||
config.history = 8;
|
||||
let client = Client::new(
|
||||
config,
|
||||
@@ -122,19 +135,24 @@ mod block_tests {
|
||||
declare_test!{BlockchainTests_bcInvalidHeaderTest, "BlockchainTests/bcInvalidHeaderTest"}
|
||||
declare_test!{BlockchainTests_bcMultiChainTest, "BlockchainTests/bcMultiChainTest"}
|
||||
declare_test!{BlockchainTests_bcRandomBlockhashTest, "BlockchainTests/bcRandomBlockhashTest"}
|
||||
declare_test!{BlockchainTests_bcStateTest, "BlockchainTests/bcStateTests"}
|
||||
declare_test!{BlockchainTests_bcTotalDifficultyTest, "BlockchainTests/bcTotalDifficultyTest"}
|
||||
declare_test!{BlockchainTests_bcUncleHeaderValidity, "BlockchainTests/bcUncleHeaderValidity"}
|
||||
declare_test!{BlockchainTests_bcUncleTest, "BlockchainTests/bcUncleTest"}
|
||||
declare_test!{BlockchainTests_bcValidBlockTest, "BlockchainTests/bcValidBlockTest"}
|
||||
declare_test!{BlockchainTests_bcWalletTest, "BlockchainTests/bcWalletTest"}
|
||||
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stArgsZeroOneBalance, "BlockchainTests/GeneralStateTests/stArgsZeroOneBalance/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stAttackTest, "BlockchainTests/GeneralStateTests/stAttackTest/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stBadOpcodeTest, "BlockchainTests/GeneralStateTests/stBadOpcode/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stBugsTest, "BlockchainTests/GeneralStateTests/stBugs/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stCallCodes, "BlockchainTests/GeneralStateTests/stCallCodes/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stCallCreateCallCodeTest, "BlockchainTests/GeneralStateTests/stCallCreateCallCodeTest/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stCallDelegateCodesCallCodeHomestead, "BlockchainTests/GeneralStateTests/stCallDelegateCodesCallCodeHomestead/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stCallDelegateCodesHomestead, "BlockchainTests/GeneralStateTests/stCallDelegateCodesHomestead/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stChangedEIP150, "BlockchainTests/GeneralStateTests/stChangedEIP150/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stCodeSizeLimit, "BlockchainTests/GeneralStateTests/stCodeSizeLimit/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stCreate2, "BlockchainTests/GeneralStateTests/stCreate2/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stCreateTest, "BlockchainTests/GeneralStateTests/stCreateTest/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stDelegatecallTestHomestead, "BlockchainTests/GeneralStateTests/stDelegatecallTestHomestead/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stEIP150singleCodeGasPrices, "BlockchainTests/GeneralStateTests/stEIP150singleCodeGasPrices/"}
|
||||
@@ -149,12 +167,15 @@ mod block_tests {
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stMemoryTest, "BlockchainTests/GeneralStateTests/stMemoryTest/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stNonZeroCallsTest, "BlockchainTests/GeneralStateTests/stNonZeroCallsTest/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stPreCompiledContracts, "BlockchainTests/GeneralStateTests/stPreCompiledContracts/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stPreCompiledContracts2, "BlockchainTests/GeneralStateTests/stPreCompiledContracts2/"}
|
||||
declare_test!{heavy => BlockchainTests_GeneralStateTest_stQuadraticComplexityTest, "BlockchainTests/GeneralStateTests/stQuadraticComplexityTest/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stRandom, "BlockchainTests/GeneralStateTests/stRandom/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stRandom2, "BlockchainTests/GeneralStateTests/stRandom2/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stRecursiveCreate, "BlockchainTests/GeneralStateTests/stRecursiveCreate/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stRefundTest, "BlockchainTests/GeneralStateTests/stRefundTest/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stReturnDataTest, "BlockchainTests/GeneralStateTests/stReturnDataTest/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stRevertTest, "BlockchainTests/GeneralStateTests/stRevertTest/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stShift, "BlockchainTests/GeneralStateTests/stShift/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stSolidityTest, "BlockchainTests/GeneralStateTests/stSolidityTest/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stSpecialTest, "BlockchainTests/GeneralStateTests/stSpecialTest/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stStackTests, "BlockchainTests/GeneralStateTests/stStackTests/"}
|
||||
@@ -166,6 +187,8 @@ mod block_tests {
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stZeroCallsRevert, "BlockchainTests/GeneralStateTests/stZeroCallsRevert/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stZeroCallsTest, "BlockchainTests/GeneralStateTests/stZeroCallsTest/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stZeroKnowledge, "BlockchainTests/GeneralStateTests/stZeroKnowledge/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stZeroKnowledge2, "BlockchainTests/GeneralStateTests/stZeroKnowledge2/"}
|
||||
declare_test!{BlockchainTests_GeneralStateTest_stSStoreTest, "BlockchainTests/GeneralStateTests/stSStoreTest/"}
|
||||
|
||||
declare_test!{BlockchainTests_TransitionTests_bcEIP158ToByzantium, "BlockchainTests/TransitionTests/bcEIP158ToByzantium/"}
|
||||
declare_test!{BlockchainTests_TransitionTests_bcFrontierToHomestead, "BlockchainTests/TransitionTests/bcFrontierToHomestead/"}
|
||||
|
||||
@@ -95,10 +95,11 @@ mod difficulty_test_foundation {
|
||||
declare_test!{DifficultyTests_difficultyMainNetwork, "BasicTests/difficultyMainNetwork.json"}
|
||||
}
|
||||
|
||||
mod difficulty_test_ropsten {
|
||||
difficulty_json_test_nopath!(new_ropsten_test);
|
||||
declare_test!{DifficultyTests_difficultyRopsten, "BasicTests/difficultyRopsten.json"}
|
||||
}
|
||||
// Disabling Ropsten diff tests; waiting for upstream ethereum/tests Constantinople update
|
||||
//mod difficulty_test_ropsten {
|
||||
// difficulty_json_test_nopath!(new_ropsten_test);
|
||||
// declare_test!{DifficultyTests_difficultyRopsten, "BasicTests/difficultyRopsten.json"}
|
||||
//}
|
||||
|
||||
mod difficulty_test_frontier {
|
||||
difficulty_json_test_nopath!(new_frontier_test);
|
||||
|
||||
@@ -88,7 +88,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> TestExt<'a, T, V, B>
|
||||
machine: &'a Machine,
|
||||
schedule: &'a Schedule,
|
||||
depth: usize,
|
||||
origin_info: OriginInfo,
|
||||
origin_info: &'a OriginInfo,
|
||||
substate: &'a mut Substate,
|
||||
output: OutputPolicy,
|
||||
address: Address,
|
||||
@@ -98,7 +98,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> TestExt<'a, T, V, B>
|
||||
let static_call = false;
|
||||
Ok(TestExt {
|
||||
nonce: state.nonce(&address)?,
|
||||
ext: Externalities::new(state, info, machine, schedule, depth, origin_info, substate, output, tracer, vm_tracer, static_call),
|
||||
ext: Externalities::new(state, info, machine, schedule, depth, 0, origin_info, substate, output, tracer, vm_tracer, static_call),
|
||||
callcreates: vec![],
|
||||
sender: address,
|
||||
})
|
||||
@@ -140,7 +140,14 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for TestExt<'a, T, V, B>
|
||||
self.ext.blockhash(number)
|
||||
}
|
||||
|
||||
fn create(&mut self, gas: &U256, value: &U256, code: &[u8], address: CreateContractAddress) -> ContractCreateResult {
|
||||
fn create(
|
||||
&mut self,
|
||||
gas: &U256,
|
||||
value: &U256,
|
||||
code: &[u8],
|
||||
address: CreateContractAddress,
|
||||
_trap: bool
|
||||
) -> Result<ContractCreateResult, vm::TrapKind> {
|
||||
self.callcreates.push(CallCreate {
|
||||
data: code.to_vec(),
|
||||
destination: None,
|
||||
@@ -148,25 +155,27 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for TestExt<'a, T, V, B>
|
||||
value: *value
|
||||
});
|
||||
let contract_address = contract_address(address, &self.sender, &self.nonce, &code).0;
|
||||
ContractCreateResult::Created(contract_address, *gas)
|
||||
Ok(ContractCreateResult::Created(contract_address, *gas))
|
||||
}
|
||||
|
||||
fn call(&mut self,
|
||||
fn call(
|
||||
&mut self,
|
||||
gas: &U256,
|
||||
_sender_address: &Address,
|
||||
receive_address: &Address,
|
||||
value: Option<U256>,
|
||||
data: &[u8],
|
||||
_code_address: &Address,
|
||||
_call_type: CallType
|
||||
) -> MessageCallResult {
|
||||
_call_type: CallType,
|
||||
_trap: bool
|
||||
) -> Result<MessageCallResult, vm::TrapKind> {
|
||||
self.callcreates.push(CallCreate {
|
||||
data: data.to_vec(),
|
||||
destination: Some(receive_address.clone()),
|
||||
gas_limit: *gas,
|
||||
value: value.unwrap()
|
||||
});
|
||||
MessageCallResult::Success(*gas, ReturnData::empty())
|
||||
Ok(MessageCallResult::Success(*gas, ReturnData::empty()))
|
||||
}
|
||||
|
||||
fn extcode(&self, address: &Address) -> vm::Result<Option<Arc<Bytes>>> {
|
||||
@@ -209,11 +218,11 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for TestExt<'a, T, V, B>
|
||||
false
|
||||
}
|
||||
|
||||
fn add_sstore_refund(&mut self, value: U256) {
|
||||
fn add_sstore_refund(&mut self, value: usize) {
|
||||
self.ext.add_sstore_refund(value)
|
||||
}
|
||||
|
||||
fn sub_sstore_refund(&mut self, value: U256) {
|
||||
fn sub_sstore_refund(&mut self, value: usize) {
|
||||
self.ext.sub_sstore_refund(value)
|
||||
}
|
||||
}
|
||||
@@ -270,6 +279,7 @@ fn do_json_test_for<H: FnMut(&str, HookType)>(vm_type: &VMType, json_data: &[u8]
|
||||
let mut tracer = NoopTracer;
|
||||
let mut vm_tracer = NoopVMTracer;
|
||||
let vm_factory = state.vm_factory();
|
||||
let origin_info = OriginInfo::from(¶ms);
|
||||
|
||||
// execute
|
||||
let (res, callcreates) = {
|
||||
@@ -280,7 +290,7 @@ fn do_json_test_for<H: FnMut(&str, HookType)>(vm_type: &VMType, json_data: &[u8]
|
||||
&machine,
|
||||
&schedule,
|
||||
0,
|
||||
OriginInfo::from(¶ms),
|
||||
&origin_info,
|
||||
&mut substate,
|
||||
OutputPolicy::Return,
|
||||
params.address.clone(),
|
||||
@@ -288,7 +298,7 @@ fn do_json_test_for<H: FnMut(&str, HookType)>(vm_type: &VMType, json_data: &[u8]
|
||||
&mut vm_tracer,
|
||||
));
|
||||
let mut evm = vm_factory.create(params, &schedule, 0);
|
||||
let res = evm.exec(&mut ex);
|
||||
let res = evm.exec(&mut ex).ok().expect("TestExt never trap; resume error never happens; qed");
|
||||
// a return in finalize will not alter callcreates
|
||||
let callcreates = ex.callcreates.clone();
|
||||
(res.finalize(ex), callcreates)
|
||||
|
||||
@@ -24,10 +24,12 @@ mod executive;
|
||||
mod state;
|
||||
mod chain;
|
||||
mod trie;
|
||||
mod skip;
|
||||
|
||||
#[cfg(test)]
|
||||
mod difficulty;
|
||||
|
||||
|
||||
pub use self::test_common::HookType;
|
||||
|
||||
pub use self::transaction::run_test_path as run_transaction_test_path;
|
||||
@@ -42,3 +44,4 @@ pub use self::trie::run_generic_test_path as run_generic_trie_test_path;
|
||||
pub use self::trie::run_generic_test_file as run_generic_trie_test_file;
|
||||
pub use self::trie::run_secure_test_path as run_secure_trie_test_path;
|
||||
pub use self::trie::run_secure_test_file as run_secure_trie_test_file;
|
||||
use self::skip::SKIP_TEST_STATE;
|
||||
|
||||
37
ethcore/src/json_tests/skip.rs
Normal file
37
ethcore/src/json_tests/skip.rs
Normal file
@@ -0,0 +1,37 @@
|
||||
// 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/>.
|
||||
|
||||
//! State tests to skip.
|
||||
|
||||
use ethjson;
|
||||
|
||||
#[cfg(all(not(test), feature = "ci-skip-tests"))]
|
||||
compile_error!("ci-skip-tests can only be enabled for testing builds.");
|
||||
|
||||
#[cfg(feature="ci-skip-issue")]
|
||||
lazy_static!{
|
||||
pub static ref SKIP_TEST_STATE: ethjson::test::SkipStates = {
|
||||
let skip_data = include_bytes!("../../res/ethereum/tests-issues/currents.json");
|
||||
ethjson::test::SkipStates::load(&skip_data[..]).expect("No invalid json allowed")
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(not(feature="ci-skip-issue"))]
|
||||
lazy_static!{
|
||||
pub static ref SKIP_TEST_STATE: ethjson::test::SkipStates = {
|
||||
ethjson::test::SkipStates::empty()
|
||||
};
|
||||
}
|
||||
@@ -22,7 +22,7 @@ use client::{EvmTestClient, EvmTestError, TransactResult};
|
||||
use ethjson;
|
||||
use transaction::SignedTransaction;
|
||||
use vm::EnvInfo;
|
||||
|
||||
use super::SKIP_TEST_STATE;
|
||||
use super::HookType;
|
||||
|
||||
/// Run state jsontests on a given folder.
|
||||
@@ -35,6 +35,18 @@ pub fn run_test_file<H: FnMut(&str, HookType)>(p: &Path, h: &mut H) {
|
||||
::json_tests::test_common::run_test_file(p, json_chain_test, h)
|
||||
}
|
||||
|
||||
fn skip_test(subname: &str, chain: &String, number: usize) -> bool {
|
||||
SKIP_TEST_STATE.state.iter().any(|state_test|{
|
||||
if let Some(subtest) = state_test.subtests.get(subname) {
|
||||
chain == &subtest.chain &&
|
||||
(subtest.subnumbers[0] == "*"
|
||||
|| subtest.subnumbers.contains(&number.to_string()))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn json_chain_test<H: FnMut(&str, HookType)>(json_data: &[u8], start_stop_hook: &mut H) -> Vec<String> {
|
||||
::ethcore_logger::init_log();
|
||||
let tests = ethjson::state::test::Test::load(json_data).unwrap();
|
||||
@@ -60,6 +72,10 @@ pub fn json_chain_test<H: FnMut(&str, HookType)>(json_data: &[u8], start_stop_ho
|
||||
|
||||
for (i, state) in states.into_iter().enumerate() {
|
||||
let info = format!(" - {} | {:?} ({}/{}) ...", name, spec_name, i + 1, total);
|
||||
if skip_test(&name, &spec.name, i + 1) {
|
||||
println!("{} in skip list : SKIPPED", info);
|
||||
continue;
|
||||
}
|
||||
|
||||
let post_root: H256 = state.hash.into();
|
||||
let transaction: SignedTransaction = multitransaction.select(&state.indexes).into();
|
||||
@@ -125,11 +141,13 @@ mod state_tests {
|
||||
declare_test!{GeneralStateTest_stChangedEIP150, "GeneralStateTests/stChangedEIP150/"}
|
||||
declare_test!{GeneralStateTest_stCodeCopyTest, "GeneralStateTests/stCodeCopyTest/"}
|
||||
declare_test!{GeneralStateTest_stCodeSizeLimit, "GeneralStateTests/stCodeSizeLimit/"}
|
||||
declare_test!{GeneralStateTest_stCreate2Test, "GeneralStateTests/stCreate2/"}
|
||||
declare_test!{GeneralStateTest_stCreateTest, "GeneralStateTests/stCreateTest/"}
|
||||
declare_test!{GeneralStateTest_stDelegatecallTestHomestead, "GeneralStateTests/stDelegatecallTestHomestead/"}
|
||||
declare_test!{GeneralStateTest_stEIP150singleCodeGasPrices, "GeneralStateTests/stEIP150singleCodeGasPrices/"}
|
||||
declare_test!{GeneralStateTest_stEIP150Specific, "GeneralStateTests/stEIP150Specific/"}
|
||||
declare_test!{GeneralStateTest_stEIP158Specific, "GeneralStateTests/stEIP158Specific/"}
|
||||
declare_test!{GeneralStateTest_stEWASMTests, "GeneralStateTests/stEWASMTests/"}
|
||||
declare_test!{GeneralStateTest_stExample, "GeneralStateTests/stExample/"}
|
||||
declare_test!{GeneralStateTest_stHomesteadSpecific, "GeneralStateTests/stHomesteadSpecific/"}
|
||||
declare_test!{GeneralStateTest_stInitCodeTest, "GeneralStateTests/stInitCodeTest/"}
|
||||
@@ -147,6 +165,7 @@ mod state_tests {
|
||||
declare_test!{GeneralStateTest_stRefundTest, "GeneralStateTests/stRefundTest/"}
|
||||
declare_test!{GeneralStateTest_stReturnDataTest, "GeneralStateTests/stReturnDataTest/"}
|
||||
declare_test!{GeneralStateTest_stRevertTest, "GeneralStateTests/stRevertTest/"}
|
||||
declare_test!{GeneralStateTest_stSStoreTest, "GeneralStateTests/stSStoreTest/"}
|
||||
declare_test!{GeneralStateTest_stShift, "GeneralStateTests/stShift/"}
|
||||
declare_test!{GeneralStateTest_stSolidityTest, "GeneralStateTests/stSolidityTest/"}
|
||||
declare_test!{GeneralStateTest_stSpecialTest, "GeneralStateTests/stSpecialTest/"}
|
||||
|
||||
@@ -34,6 +34,18 @@ pub fn run_test_path<H: FnMut(&str, HookType)>(
|
||||
p: &Path, skip: &[&'static str],
|
||||
runner: fn(json_data: &[u8], start_stop_hook: &mut H) -> Vec<String>,
|
||||
start_stop_hook: &mut H
|
||||
) {
|
||||
let mut errors = Vec::new();
|
||||
run_test_path_inner(p, skip, runner, start_stop_hook, &mut errors);
|
||||
let empty: [String; 0] = [];
|
||||
assert_eq!(errors, empty);
|
||||
}
|
||||
|
||||
fn run_test_path_inner<H: FnMut(&str, HookType)>(
|
||||
p: &Path, skip: &[&'static str],
|
||||
runner: fn(json_data: &[u8], start_stop_hook: &mut H) -> Vec<String>,
|
||||
start_stop_hook: &mut H,
|
||||
errors: &mut Vec<String>
|
||||
) {
|
||||
let path = Path::new(p);
|
||||
let s: HashSet<OsString> = skip.iter().map(|s| {
|
||||
@@ -50,17 +62,32 @@ pub fn run_test_path<H: FnMut(&str, HookType)>(
|
||||
} else {
|
||||
Some(e.path())
|
||||
}}) {
|
||||
run_test_path(&p, skip, runner, start_stop_hook)
|
||||
run_test_path_inner(&p, skip, runner, start_stop_hook, errors);
|
||||
}
|
||||
} else if extension == Some("swp") || extension == None {
|
||||
// Ignore junk
|
||||
} else {
|
||||
let mut path = p.to_path_buf();
|
||||
path.set_extension("json");
|
||||
run_test_file(&path, runner, start_stop_hook)
|
||||
run_test_file_append(&path, runner, start_stop_hook, errors)
|
||||
}
|
||||
}
|
||||
|
||||
fn run_test_file_append<H: FnMut(&str, HookType)>(
|
||||
path: &Path,
|
||||
runner: fn(json_data: &[u8], start_stop_hook: &mut H) -> Vec<String>,
|
||||
start_stop_hook: &mut H,
|
||||
errors: &mut Vec<String>
|
||||
) {
|
||||
let mut data = Vec::new();
|
||||
let mut file = match File::open(&path) {
|
||||
Ok(file) => file,
|
||||
Err(_) => panic!("Error opening test file at: {:?}", path),
|
||||
};
|
||||
file.read_to_end(&mut data).expect("Error reading test file");
|
||||
errors.append(&mut runner(&data, start_stop_hook));
|
||||
}
|
||||
|
||||
pub fn run_test_file<H: FnMut(&str, HookType)>(
|
||||
path: &Path,
|
||||
runner: fn(json_data: &[u8], start_stop_hook: &mut H) -> Vec<String>,
|
||||
|
||||
@@ -20,6 +20,7 @@ use ethtrie::RlpCodec;
|
||||
use ethereum_types::H256;
|
||||
use memorydb::MemoryDB;
|
||||
use keccak_hasher::KeccakHasher;
|
||||
use kvdb::DBValue;
|
||||
|
||||
use super::HookType;
|
||||
|
||||
@@ -36,7 +37,7 @@ fn test_trie<H: FnMut(&str, HookType)>(json: &[u8], trie: TrieSpec, start_stop_h
|
||||
for (name, test) in tests.into_iter() {
|
||||
start_stop_hook(&name, HookType::OnStart);
|
||||
|
||||
let mut memdb = MemoryDB::<KeccakHasher>::new();
|
||||
let mut memdb = MemoryDB::<KeccakHasher, DBValue>::new();
|
||||
let mut root = H256::default();
|
||||
let mut t = factory.create(&mut memdb, &mut root);
|
||||
|
||||
|
||||
@@ -139,6 +139,9 @@ extern crate trace_time;
|
||||
#[cfg_attr(test, macro_use)]
|
||||
extern crate evm;
|
||||
|
||||
#[cfg(test)]
|
||||
extern crate env_logger;
|
||||
|
||||
pub extern crate ethstore;
|
||||
|
||||
#[macro_use]
|
||||
@@ -159,6 +162,7 @@ pub mod header;
|
||||
pub mod machine;
|
||||
pub mod miner;
|
||||
pub mod pod_state;
|
||||
pub mod pod_account;
|
||||
pub mod snapshot;
|
||||
pub mod spec;
|
||||
pub mod state;
|
||||
@@ -167,7 +171,6 @@ pub mod trace;
|
||||
pub mod verification;
|
||||
|
||||
mod cache_manager;
|
||||
mod pod_account;
|
||||
mod account_db;
|
||||
mod externalities;
|
||||
mod blockchain;
|
||||
|
||||
@@ -135,8 +135,10 @@ impl EthereumMachine {
|
||||
Some(contract_address),
|
||||
code,
|
||||
code_hash,
|
||||
None,
|
||||
gas,
|
||||
data
|
||||
data,
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -149,8 +151,10 @@ impl EthereumMachine {
|
||||
contract_address: Option<Address>,
|
||||
code: Option<Arc<Vec<u8>>>,
|
||||
code_hash: Option<H256>,
|
||||
value: Option<ActionValue>,
|
||||
gas: U256,
|
||||
data: Option<Vec<u8>>
|
||||
data: Option<Vec<u8>>,
|
||||
call_type: Option<CallType>,
|
||||
) -> Result<Vec<u8>, Error> {
|
||||
let env_info = {
|
||||
let mut env_info = block.env_info();
|
||||
@@ -167,11 +171,11 @@ impl EthereumMachine {
|
||||
origin: SYSTEM_ADDRESS,
|
||||
gas,
|
||||
gas_price: 0.into(),
|
||||
value: ActionValue::Transfer(0.into()),
|
||||
value: value.unwrap_or(ActionValue::Transfer(0.into())),
|
||||
code,
|
||||
code_hash,
|
||||
data,
|
||||
call_type: CallType::Call,
|
||||
call_type: call_type.unwrap_or(CallType::Call),
|
||||
params_type: ParamsType::Separate,
|
||||
};
|
||||
let schedule = self.schedule(env_info.number);
|
||||
@@ -367,11 +371,11 @@ impl EthereumMachine {
|
||||
}
|
||||
|
||||
/// Does verification of the transaction against the parent state.
|
||||
pub fn verify_transaction<C: BlockInfo + CallContract>(&self, t: &SignedTransaction, header: &Header, client: &C)
|
||||
pub fn verify_transaction<C: BlockInfo + CallContract>(&self, t: &SignedTransaction, parent: &Header, client: &C)
|
||||
-> Result<(), transaction::Error>
|
||||
{
|
||||
if let Some(ref filter) = self.tx_filter.as_ref() {
|
||||
if !filter.transaction_allowed(header.parent_hash(), header.number(), t, client) {
|
||||
if !filter.transaction_allowed(&parent.hash(), parent.number() + 1, t, client) {
|
||||
return Err(transaction::Error::NotAllowed.into())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ use executive::contract_address;
|
||||
use header::{Header, BlockNumber};
|
||||
use miner;
|
||||
use miner::pool_client::{PoolClient, CachedNonceClient, NonceCache};
|
||||
use receipt::{Receipt, RichReceipt};
|
||||
use receipt::RichReceipt;
|
||||
use spec::Spec;
|
||||
use state::State;
|
||||
use ethkey::Password;
|
||||
@@ -576,10 +576,9 @@ impl Miner {
|
||||
trace!(target: "miner", "requires_reseal: sealing enabled");
|
||||
|
||||
// Disable sealing if there were no requests for SEALING_TIMEOUT_IN_BLOCKS
|
||||
let had_requests = sealing.last_request.map(|last_request| {
|
||||
best_block > last_request
|
||||
&& best_block - last_request <= SEALING_TIMEOUT_IN_BLOCKS
|
||||
}).unwrap_or(false);
|
||||
let had_requests = sealing.last_request.map(|last_request|
|
||||
best_block.saturating_sub(last_request) <= SEALING_TIMEOUT_IN_BLOCKS
|
||||
).unwrap_or(false);
|
||||
|
||||
// keep sealing enabled if any of the conditions is met
|
||||
let sealing_enabled = self.forced_sealing()
|
||||
@@ -938,6 +937,10 @@ impl miner::MinerService for Miner {
|
||||
self.transaction_queue.all_transactions()
|
||||
}
|
||||
|
||||
fn queued_transaction_hashes(&self) -> Vec<H256> {
|
||||
self.transaction_queue.all_transaction_hashes()
|
||||
}
|
||||
|
||||
fn pending_transaction_hashes<C>(&self, chain: &C) -> BTreeSet<H256> where
|
||||
C: ChainInfo + Sync,
|
||||
{
|
||||
@@ -1039,19 +1042,17 @@ impl miner::MinerService for Miner {
|
||||
self.transaction_queue.status()
|
||||
}
|
||||
|
||||
fn pending_receipt(&self, best_block: BlockNumber, hash: &H256) -> Option<RichReceipt> {
|
||||
fn pending_receipts(&self, best_block: BlockNumber) -> Option<Vec<RichReceipt>> {
|
||||
self.map_existing_pending_block(|pending| {
|
||||
let txs = pending.transactions();
|
||||
txs.iter()
|
||||
.map(|t| t.hash())
|
||||
.position(|t| t == *hash)
|
||||
.map(|index| {
|
||||
let receipts = pending.receipts();
|
||||
let receipts = pending.receipts();
|
||||
pending.transactions()
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(index, tx)| {
|
||||
let prev_gas = if index == 0 { Default::default() } else { receipts[index - 1].gas_used };
|
||||
let tx = &txs[index];
|
||||
let receipt = &receipts[index];
|
||||
RichReceipt {
|
||||
transaction_hash: hash.clone(),
|
||||
transaction_hash: tx.hash(),
|
||||
transaction_index: index,
|
||||
cumulative_gas_used: receipt.gas_used,
|
||||
gas_used: receipt.gas_used - prev_gas,
|
||||
@@ -1067,15 +1068,7 @@ impl miner::MinerService for Miner {
|
||||
outcome: receipt.outcome.clone(),
|
||||
}
|
||||
})
|
||||
}, best_block).and_then(|x| x)
|
||||
}
|
||||
|
||||
fn pending_receipts(&self, best_block: BlockNumber) -> Option<BTreeMap<H256, Receipt>> {
|
||||
self.map_existing_pending_block(|pending| {
|
||||
let hashes = pending.transactions().iter().map(|t| t.hash());
|
||||
let receipts = pending.receipts().iter().cloned();
|
||||
|
||||
hashes.zip(receipts).collect()
|
||||
.collect()
|
||||
}, best_block)
|
||||
}
|
||||
|
||||
@@ -1400,6 +1393,33 @@ mod tests {
|
||||
assert_eq!(miner.prepare_pending_block(&client), BlockPreparationStatus::NotPrepared);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_return_stale_work_packages() {
|
||||
// given
|
||||
let client = TestBlockChainClient::default();
|
||||
let miner = miner();
|
||||
|
||||
// initial work package should create the pending block
|
||||
let res = miner.work_package(&client);
|
||||
assert_eq!(res.unwrap().1, 1);
|
||||
// This should be true, since there were some requests.
|
||||
assert_eq!(miner.requires_reseal(0), true);
|
||||
|
||||
// when new block is imported
|
||||
let client = generate_dummy_client(2);
|
||||
let imported = [0.into()];
|
||||
let empty = &[];
|
||||
miner.chain_new_blocks(&*client, &imported, empty, &imported, empty, false);
|
||||
|
||||
// then
|
||||
// This should be false, because it's too early.
|
||||
assert_eq!(miner.requires_reseal(2), false);
|
||||
// but still work package should be ready
|
||||
let res = miner.work_package(&*client);
|
||||
assert_eq!(res.unwrap().1, 3);
|
||||
assert_eq!(miner.prepare_pending_block(&*client), BlockPreparationStatus::NotPrepared);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_use_pending_block_if_best_block_is_higher() {
|
||||
// given
|
||||
|
||||
@@ -44,7 +44,7 @@ use client::{
|
||||
};
|
||||
use error::Error;
|
||||
use header::{BlockNumber, Header};
|
||||
use receipt::{RichReceipt, Receipt};
|
||||
use receipt::RichReceipt;
|
||||
use transaction::{self, UnverifiedTransaction, SignedTransaction, PendingTransaction};
|
||||
use state::StateInfo;
|
||||
use ethkey::Password;
|
||||
@@ -95,10 +95,13 @@ pub trait MinerService : Send + Sync {
|
||||
// Pending block
|
||||
|
||||
/// Get a list of all pending receipts from pending block.
|
||||
fn pending_receipts(&self, best_block: BlockNumber) -> Option<BTreeMap<H256, Receipt>>;
|
||||
fn pending_receipts(&self, best_block: BlockNumber) -> Option<Vec<RichReceipt>>;
|
||||
|
||||
/// Get a particular receipt from pending block.
|
||||
fn pending_receipt(&self, best_block: BlockNumber, hash: &H256) -> Option<RichReceipt>;
|
||||
fn pending_receipt(&self, best_block: BlockNumber, hash: &H256) -> Option<RichReceipt> {
|
||||
let receipts = self.pending_receipts(best_block)?;
|
||||
receipts.into_iter().find(|r| &r.transaction_hash == hash)
|
||||
}
|
||||
|
||||
/// Get `Some` `clone()` of the current pending block's state or `None` if we're not sealing.
|
||||
fn pending_state(&self, latest_block_number: BlockNumber) -> Option<Self::State>;
|
||||
@@ -182,6 +185,9 @@ pub trait MinerService : Send + Sync {
|
||||
/// Get a list of all transactions in the pool (some of them might not be ready for inclusion yet).
|
||||
fn queued_transactions(&self) -> Vec<Arc<VerifiedTransaction>>;
|
||||
|
||||
/// Get a list of all transaction hashes in the pool (some of them might not be ready for inclusion yet).
|
||||
fn queued_transaction_hashes(&self) -> Vec<H256>;
|
||||
|
||||
/// Get a list of local transactions with statuses.
|
||||
fn local_transactions(&self) -> BTreeMap<H256, local_transactions::Status>;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user