Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
09f77575d6 | ||
|
ef8f95e007 | ||
|
db3a98903b | ||
|
93b25d5242 | ||
|
7658d22f3a | ||
|
1b3b115e55 | ||
|
549e202fc1 | ||
|
de974fe954 | ||
|
7dc4d349a1 | ||
|
47d7197fb9 | ||
|
e2e1d221d5 | ||
|
a0a2beddfe | ||
|
e7dc0bed16 | ||
|
6eae372524 |
347
.gitlab-ci.yml
347
.gitlab-ci.yml
@ -1,232 +1,181 @@
|
||||
stages:
|
||||
- test
|
||||
- push-release
|
||||
- build
|
||||
- publish
|
||||
- optional
|
||||
|
||||
image: parity/rust:gitlab-ci
|
||||
|
||||
variables:
|
||||
RUST_BACKTRACE: "1"
|
||||
RUSTFLAGS: ""
|
||||
CARGOFLAGS: ""
|
||||
CI_SERVER_NAME: "GitLab CI"
|
||||
CI_SERVER_NAME: "GitLab CI"
|
||||
CARGO_HOME: "${CI_PROJECT_DIR}/.cargo"
|
||||
BUILD_TARGET: ubuntu
|
||||
BUILD_ARCH: amd64
|
||||
CARGO_TARGET: x86_64-unknown-linux-gnu
|
||||
|
||||
cache:
|
||||
key: "$CI_BUILD_STAGE-$CI_BUILD_REF_NAME"
|
||||
key: "${CI_JOB_NAME}"
|
||||
paths:
|
||||
- target/
|
||||
untracked: true
|
||||
linux-amd64:
|
||||
stage: build
|
||||
image: parity/rust:gitlab-ci
|
||||
only:
|
||||
- ./target
|
||||
- ./.cargo
|
||||
|
||||
.releaseable_branches: # list of git refs for building GitLab artifacts (think "pre-release binaries")
|
||||
only: &releaseable_branches
|
||||
- stable
|
||||
- beta
|
||||
- tags
|
||||
- stable
|
||||
- triggers
|
||||
- schedules
|
||||
|
||||
.collect_artifacts: &collect_artifacts
|
||||
artifacts:
|
||||
name: "${CI_JOB_NAME}_${CI_COMMIT_REF_NAME}"
|
||||
when: on_success
|
||||
expire_in: 1 mos
|
||||
paths:
|
||||
- artifacts/
|
||||
|
||||
.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 "${CI_COMMIT_REF_NAME}" = "nightly" && VERSION="${VERSION}-${ID_SHORT}-${DATE_STR}"
|
||||
- export VERSION
|
||||
- echo "Version = ${VERSION}"
|
||||
|
||||
test-linux:
|
||||
stage: test
|
||||
variables:
|
||||
RUN_TESTS: cargo
|
||||
script:
|
||||
- rustup default stable
|
||||
# ARGUMENTS: 1. BUILD_PLATFORM (target for binaries) 2. PLATFORM (target for cargo) 3. ARC (architecture) 4. & 5. CC & CXX flags 6. binary identifier
|
||||
- scripts/gitlab-build.sh x86_64-unknown-linux-gnu x86_64-unknown-linux-gnu amd64 gcc g++ linux
|
||||
- scripts/gitlab/test-all.sh stable
|
||||
tags:
|
||||
- rust-stable
|
||||
artifacts:
|
||||
paths:
|
||||
- parity.zip
|
||||
name: "stable-x86_64-unknown-linux-gnu_parity"
|
||||
linux-i686:
|
||||
stage: build
|
||||
image: parity/rust-i686:gitlab-ci
|
||||
only:
|
||||
- beta
|
||||
- tags
|
||||
- stable
|
||||
- triggers
|
||||
|
||||
build-linux:
|
||||
stage: build
|
||||
only: *releaseable_branches
|
||||
variables:
|
||||
CARGO_TARGET: x86_64-unknown-linux-gnu
|
||||
script:
|
||||
- scripts/gitlab-build.sh i686-unknown-linux-gnu i686-unknown-linux-gnu i386 gcc g++ linux
|
||||
tags:
|
||||
- rust-i686
|
||||
artifacts:
|
||||
paths:
|
||||
- parity.zip
|
||||
name: "i686-unknown-linux-gnu"
|
||||
allow_failure: true
|
||||
linux-armv7:
|
||||
stage: build
|
||||
image: parity/rust-armv7:gitlab-ci
|
||||
only:
|
||||
- beta
|
||||
- tags
|
||||
- stable
|
||||
- triggers
|
||||
script:
|
||||
- scripts/gitlab-build.sh armv7-unknown-linux-gnueabihf armv7-unknown-linux-gnueabihf armhf arm-linux-gnueabihf-gcc arm-linux-gnueabihf-g++ linux
|
||||
tags:
|
||||
- rust-arm
|
||||
artifacts:
|
||||
paths:
|
||||
- parity.zip
|
||||
name: "armv7_unknown_linux_gnueabihf_parity"
|
||||
allow_failure: true
|
||||
linux-armhf:
|
||||
stage: build
|
||||
image: parity/rust-arm:gitlab-ci
|
||||
only:
|
||||
- beta
|
||||
- tags
|
||||
- stable
|
||||
- triggers
|
||||
script:
|
||||
- scripts/gitlab-build.sh arm-unknown-linux-gnueabihf arm-unknown-linux-gnueabihf armhf arm-linux-gnueabihf-gcc arm-linux-gnueabihf-g++ linux
|
||||
tags:
|
||||
- rust-arm
|
||||
artifacts:
|
||||
paths:
|
||||
- parity.zip
|
||||
name: "arm-unknown-linux-gnueabihf_parity"
|
||||
allow_failure: true
|
||||
linux-aarch64:
|
||||
stage: build
|
||||
image: parity/rust-arm64:gitlab-ci
|
||||
only:
|
||||
- beta
|
||||
- tags
|
||||
- stable
|
||||
- triggers
|
||||
script:
|
||||
- scripts/gitlab-build.sh aarch64-unknown-linux-gnu aarch64-unknown-linux-gnu arm64 aarch64-linux-gnu-gcc aarch64-linux-gnu-g++ linux
|
||||
tags:
|
||||
- rust-arm
|
||||
artifacts:
|
||||
paths:
|
||||
- parity.zip
|
||||
name: "aarch64-unknown-linux-gnu_parity"
|
||||
linux-snap:
|
||||
stage: build
|
||||
image: parity/snapcraft:gitlab-ci
|
||||
only:
|
||||
- stable
|
||||
- beta
|
||||
- tags
|
||||
- triggers
|
||||
script:
|
||||
- scripts/gitlab-build.sh x86_64-unknown-snap-gnu x86_64-unknown-linux-gnu amd64 gcc g++ snap
|
||||
- scripts/gitlab/build-unix.sh
|
||||
<<: *collect_artifacts
|
||||
tags:
|
||||
- rust-stable
|
||||
artifacts:
|
||||
paths:
|
||||
- parity.zip
|
||||
name: "stable-x86_64-unknown-snap-gnu_parity"
|
||||
darwin:
|
||||
stage: build
|
||||
only:
|
||||
- beta
|
||||
- tags
|
||||
- stable
|
||||
- triggers
|
||||
|
||||
build-darwin:
|
||||
stage: build
|
||||
only: *releaseable_branches
|
||||
variables:
|
||||
CARGO_TARGET: x86_64-apple-darwin
|
||||
CC: gcc
|
||||
CXX: g++
|
||||
script:
|
||||
- scripts/gitlab-build.sh x86_64-apple-darwin x86_64-apple-darwin macos gcc g++ macos
|
||||
- scripts/gitlab/build-unix.sh
|
||||
tags:
|
||||
- osx
|
||||
artifacts:
|
||||
paths:
|
||||
- parity.zip
|
||||
name: "x86_64-apple-darwin_parity"
|
||||
windows:
|
||||
cache:
|
||||
key: "%CI_BUILD_STAGE%-%CI_BUILD_REF_NAME%"
|
||||
untracked: true
|
||||
stage: build
|
||||
only:
|
||||
- beta
|
||||
- tags
|
||||
- stable
|
||||
- triggers
|
||||
- rust-osx
|
||||
<<: *collect_artifacts
|
||||
|
||||
build-windows:
|
||||
stage: build
|
||||
only: *releaseable_branches
|
||||
variables:
|
||||
CARGO_TARGET: x86_64-pc-windows-msvc
|
||||
script:
|
||||
- sh scripts/gitlab-build.sh x86_64-pc-windows-msvc x86_64-pc-windows-msvc amd64 "" "" windows
|
||||
- sh scripts/gitlab/build-windows.sh
|
||||
tags:
|
||||
- rust-windows
|
||||
artifacts:
|
||||
paths:
|
||||
- parity.zip
|
||||
name: "x86_64-pc-windows-msvc_parity"
|
||||
android-armv7:
|
||||
stage: build
|
||||
image: parity/parity-android:latest
|
||||
only:
|
||||
- beta
|
||||
- tags
|
||||
- stable
|
||||
- triggers
|
||||
script:
|
||||
- cargo build --target=armv7-linux-androideabi
|
||||
<<: *collect_artifacts
|
||||
|
||||
publish-docker:
|
||||
stage: publish
|
||||
only: *releaseable_branches
|
||||
cache: {}
|
||||
dependencies:
|
||||
- build-linux
|
||||
tags:
|
||||
- rust-arm
|
||||
allow_failure: true
|
||||
artifacts:
|
||||
paths:
|
||||
- parity.zip
|
||||
name: "armv7-linux-androideabi_parity"
|
||||
docker-build:
|
||||
stage: build
|
||||
- shell
|
||||
script:
|
||||
- scripts/gitlab/publish-docker.sh parity
|
||||
|
||||
publish-awss3:
|
||||
stage: publish
|
||||
only: *releaseable_branches
|
||||
cache: {}
|
||||
dependencies:
|
||||
- build-linux
|
||||
- build-darwin
|
||||
- build-windows
|
||||
before_script: *determine_version
|
||||
script:
|
||||
- scripts/gitlab/publish-awss3.sh
|
||||
tags:
|
||||
- shell
|
||||
|
||||
docs-jsonrpc:
|
||||
stage: optional
|
||||
only:
|
||||
- tags
|
||||
- master
|
||||
- beta
|
||||
- stable
|
||||
- triggers
|
||||
before_script:
|
||||
- docker info
|
||||
except:
|
||||
- nightly
|
||||
cache: {}
|
||||
script:
|
||||
- if [ "$CI_BUILD_REF_NAME" == "master" ]; then DOCKER_TAG="latest"; else DOCKER_TAG=$CI_BUILD_REF_NAME; fi
|
||||
- echo "Tag:" $DOCKER_TAG
|
||||
- docker login -u $Docker_Hub_User_Parity -p $Docker_Hub_Pass_Parity
|
||||
- scripts/docker-build.sh $DOCKER_TAG
|
||||
- docker logout
|
||||
- scripts/gitlab/docs-jsonrpc.sh
|
||||
tags:
|
||||
- docker
|
||||
test-coverage:
|
||||
stage: test
|
||||
only:
|
||||
- master
|
||||
- shell
|
||||
|
||||
cargo-audit:
|
||||
stage: optional
|
||||
script:
|
||||
- scripts/gitlab-test.sh test-coverage
|
||||
tags:
|
||||
- kcov
|
||||
allow_failure: true
|
||||
test-rust-stable:
|
||||
stage: test
|
||||
image: parity/rust:gitlab-ci
|
||||
script:
|
||||
- scripts/gitlab-test.sh stable
|
||||
- scripts/gitlab/cargo-audit.sh
|
||||
tags:
|
||||
- rust-stable
|
||||
test-rust-beta:
|
||||
stage: test
|
||||
only:
|
||||
- triggers
|
||||
- master
|
||||
image: parity/rust:gitlab-ci
|
||||
|
||||
test-android:
|
||||
stage: optional
|
||||
image: parity/rust-android:gitlab-ci
|
||||
variables:
|
||||
CARGO_TARGET: armv7-linux-androideabi
|
||||
script:
|
||||
- scripts/gitlab-test.sh beta
|
||||
- scripts/gitlab/test-all.sh stable
|
||||
tags:
|
||||
- rust-arm
|
||||
|
||||
test-darwin:
|
||||
stage: optional
|
||||
variables:
|
||||
CARGO_TARGET: x86_64-apple-darwin
|
||||
CC: gcc
|
||||
CXX: g++
|
||||
RUN_TESTS: cargo
|
||||
script:
|
||||
- scripts/gitlab/test-all.sh stable
|
||||
tags:
|
||||
- rust-osx
|
||||
|
||||
test-windows:
|
||||
stage: optional
|
||||
variables:
|
||||
CARGO_TARGET: x86_64-pc-windows-msvc
|
||||
RUN_TESTS: cargo
|
||||
script:
|
||||
- sh scripts/gitlab/test-all.sh stable
|
||||
tags:
|
||||
- rust-windows
|
||||
|
||||
test-beta:
|
||||
stage: optional
|
||||
variables:
|
||||
RUN_TESTS: cargo
|
||||
script:
|
||||
- scripts/gitlab/test-all.sh beta
|
||||
tags:
|
||||
- rust-beta
|
||||
allow_failure: true
|
||||
test-rust-nightly:
|
||||
stage: test
|
||||
only:
|
||||
- triggers
|
||||
- master
|
||||
image: parity/rust:gitlab-ci
|
||||
|
||||
test-nightly:
|
||||
stage: optional
|
||||
variables:
|
||||
RUN_TESTS: all
|
||||
script:
|
||||
- scripts/gitlab-test.sh nightly
|
||||
- scripts/gitlab/test-all.sh nightly
|
||||
tags:
|
||||
- rust
|
||||
- rust-nightly
|
||||
allow_failure: true
|
||||
push-release:
|
||||
stage: push-release
|
||||
only:
|
||||
- tags
|
||||
- triggers
|
||||
image: parity/rust:gitlab-ci
|
||||
script:
|
||||
- scripts/gitlab-push-release.sh
|
||||
tags:
|
||||
- curl
|
||||
|
383
Cargo.lock
generated
383
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,7 @@
|
||||
description = "Parity Ethereum client"
|
||||
name = "parity-ethereum"
|
||||
# NOTE Make sure to update util/version/Cargo.toml as well
|
||||
version = "2.0.0"
|
||||
version = "2.0.9"
|
||||
license = "GPL-3.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
@ -32,7 +32,7 @@ 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" }
|
||||
ethcore = { path = "ethcore", features = ["work-notify", "price-info", "stratum"] }
|
||||
ethcore = { path = "ethcore", features = ["parity"] }
|
||||
parity-bytes = { git = "https://github.com/paritytech/parity-common" }
|
||||
ethcore-io = { path = "util/io" }
|
||||
ethcore-light = { path = "ethcore/light" }
|
||||
@ -46,7 +46,6 @@ ethcore-transaction = { path = "ethcore/transaction" }
|
||||
ethereum-types = "0.3"
|
||||
node-filter = { path = "ethcore/node_filter" }
|
||||
ethkey = { path = "ethkey" }
|
||||
node-health = { path = "node-health" }
|
||||
rlp = { git = "https://github.com/paritytech/parity-common" }
|
||||
rpc-cli = { path = "rpc_cli" }
|
||||
parity-hash-fetch = { path = "hash-fetch" }
|
||||
@ -88,7 +87,9 @@ winapi = { version = "0.3.4", features = ["winsock2", "winuser", "shellapi"] }
|
||||
daemonize = { git = "https://github.com/paritytech/daemonize" }
|
||||
|
||||
[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"]
|
||||
|
175
README.md
175
README.md
@ -1,111 +1,75 @@
|
||||
# Parity - fast, light, and robust Ethereum client
|
||||

|
||||
|
||||
## [» Download the latest release «](https://github.com/paritytech/parity/releases/latest)
|
||||
## The fastest and most advanced Ethereum client.
|
||||
|
||||
[](https://gitlab.parity.io/parity/parity/commits/master)
|
||||
[](https://codecov.io/gh/paritytech/parity)
|
||||
[](https://build.snapcraft.io/user/paritytech/parity)
|
||||
[](https://www.gnu.org/licenses/gpl-3.0.en.html)
|
||||
<p align="center"><strong><a href="https://github.com/paritytech/parity-ethereum/releases/latest">» Download the latest release «</a></strong></p>
|
||||
|
||||
<p align="center"><a href="https://gitlab.parity.io/parity/parity-ethereum/commits/master" target="_blank"><img src="https://gitlab.parity.io/parity/parity-ethereum/badges/master/build.svg" /></a>
|
||||
<a href="https://www.gnu.org/licenses/gpl-3.0.en.html" target="_blank"><img src="https://img.shields.io/badge/license-GPL%20v3-green.svg" /></a></p>
|
||||
|
||||
### Join the chat!
|
||||
**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.
|
||||
|
||||
Get in touch with us on Gitter:
|
||||
[](https://gitter.im/paritytech/parity)
|
||||
[](https://gitter.im/paritytech/parity.js)
|
||||
[](https://gitter.im/paritytech/parity/miners)
|
||||
[](https://gitter.im/paritytech/parity-poa)
|
||||
- Clean, modular codebase for easy customisation
|
||||
- Advanced CLI-based client
|
||||
- Minimal memory and storage footprint
|
||||
- Synchronise in hours, not days with Warp Sync
|
||||
- Modular for light integration into your service or product
|
||||
|
||||
Or join our community on Matrix:
|
||||
[](https://riot.im/app/#/group/+parity:matrix.parity.io)
|
||||
## Technical Overview
|
||||
|
||||
Official website: https://parity.io | Be sure to check out [our wiki](https://wiki.parity.io) for more information.
|
||||
Parity Ethereum's goal is to be the fastest, lightest, and most secure Ethereum client. We are developing Parity Ethereum using the sophisticated and cutting-edge **Rust programming language**. Parity Ethereum is licensed under the GPLv3 and can be used for all your Ethereum needs.
|
||||
|
||||
----
|
||||
By default, Parity Ethereum runs a JSON-RPC HTTP server on port `:8545` and a Web-Sockets server on port `:8546`. This is fully configurable and supports a number of APIs.
|
||||
|
||||
## About Parity
|
||||
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's goal is to be the fastest, lightest, and most secure Ethereum client. We are developing Parity using the sophisticated and cutting-edge Rust programming language. Parity is licensed under the GPLv3, and can be used for all your Ethereum needs.
|
||||
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.
|
||||
|
||||
From Parity Ethereum client version 1.10.0, the User Interface (UI) is accessible in a separate application called Parity UI. To keep using the UI in the browser (deprecated), [follow these steps](https://wiki.parity.io/FAQ-Basic-Operations,-Configuration,-and-Synchronization#the-parity-ui-application-isnt-working-the-way-i-want).
|
||||
## Build Dependencies
|
||||
|
||||
By default, Parity will also run a JSONRPC server on `127.0.0.1:8545` and a websockets server on `127.0.0.1:8546`. This is fully configurable and supports a number of APIs.
|
||||
Parity Ethereum requires **Rust version 1.29.x** to build.
|
||||
|
||||
If you run into an issue while using Parity, feel free to file one in this repository 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's current beta-release is 1.11. You can download it at https://github.com/paritytech/parity/releases or follow the instructions below to build from source.
|
||||
|
||||
----
|
||||
|
||||
## Build dependencies
|
||||
|
||||
**Parity requires Rust version 1.26.0 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:
|
||||
We recommend installing Rust through [rustup](https://www.rustup.rs/). If you don't already have `rustup`, you can install it like this:
|
||||
|
||||
- Linux:
|
||||
```bash
|
||||
$ curl https://sh.rustup.rs -sSf | sh
|
||||
```
|
||||
|
||||
Parity also requires `gcc`, `g++`, `libssl-dev`/`openssl`, `libudev-dev`, `pkg-config`, `file` and `make` packages to be installed.
|
||||
|
||||
- OSX:
|
||||
```bash
|
||||
$ curl https://sh.rustup.rs -sSf | sh
|
||||
```
|
||||
|
||||
`clang` is required. It comes with Xcode command line tools or can be installed with homebrew.
|
||||
|
||||
- Windows
|
||||
Make sure you have Visual Studio 2015 with C++ support installed. Next, download and run the rustup installer from
|
||||
https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe, start "VS2015 x64 Native Tools Command Prompt", and use the following command to install and set up the msvc toolchain:
|
||||
```bash
|
||||
$ rustup default stable-x86_64-pc-windows-msvc
|
||||
$ curl https://sh.rustup.rs -sSf | sh
|
||||
```
|
||||
|
||||
Once you have rustup installed, then you need to install:
|
||||
Parity Ethereum also requires `gcc`, `g++`, `libudev-dev`, `pkg-config`, `file`, `make`, and `cmake` packages to be installed.
|
||||
|
||||
- OSX:
|
||||
```bash
|
||||
$ curl https://sh.rustup.rs -sSf | sh
|
||||
```
|
||||
|
||||
`clang` is required. It comes with Xcode command line tools or can be installed with homebrew.
|
||||
|
||||
- Windows
|
||||
Make sure you have Visual Studio 2015 with C++ support installed. Next, download and run the `rustup` installer from
|
||||
https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe, start "VS2015 x64 Native Tools Command Prompt", and use the following command to install and set up the `msvc` toolchain:
|
||||
```bash
|
||||
$ rustup default stable-x86_64-pc-windows-msvc
|
||||
```
|
||||
|
||||
Once you have `rustup` installed, then you need to install:
|
||||
* [Perl](https://www.perl.org)
|
||||
* [Yasm](http://yasm.tortall.net)
|
||||
* [Yasm](https://yasm.tortall.net)
|
||||
|
||||
Make sure that these binaries are in your `PATH`. After that you should be able to build parity from source.
|
||||
Make sure that these binaries are in your `PATH`. After that, you should be able to build Parity Ethereum from source.
|
||||
|
||||
----
|
||||
|
||||
## Install from the snap store
|
||||
|
||||
In any of the [supported Linux distros](https://snapcraft.io/docs/core/install):
|
||||
## Build from Source Code
|
||||
|
||||
```bash
|
||||
sudo snap install parity
|
||||
```
|
||||
|
||||
Or, if you want to contribute testing the upcoming release:
|
||||
|
||||
```bash
|
||||
sudo snap install parity --beta
|
||||
```
|
||||
|
||||
And to test the latest code landed into the master branch:
|
||||
|
||||
```bash
|
||||
sudo snap install parity --edge
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
## Build from source
|
||||
|
||||
```bash
|
||||
# download Parity code
|
||||
$ git clone https://github.com/paritytech/parity
|
||||
$ cd parity
|
||||
# download Parity Ethereum code
|
||||
$ git clone https://github.com/paritytech/parity-ethereum
|
||||
$ cd parity-ethereum
|
||||
|
||||
# build in release mode
|
||||
$ cargo build --release
|
||||
$ cargo build --release --features final
|
||||
```
|
||||
|
||||
This will produce an executable in the `./target/release` subdirectory.
|
||||
This produces an executable in the `./target/release` subdirectory.
|
||||
|
||||
Note: if cargo fails to parse manifest try:
|
||||
|
||||
@ -119,7 +83,7 @@ Note, when compiling a crate and you receive errors, it's in most cases your out
|
||||
$ cargo clean
|
||||
```
|
||||
|
||||
This will always compile the latest nightly builds. If you want to build stable or beta, do a
|
||||
This always compiles the latest nightly builds. If you want to build stable or beta, do a
|
||||
|
||||
```bash
|
||||
$ git checkout stable
|
||||
@ -131,11 +95,7 @@ or
|
||||
$ git checkout beta
|
||||
```
|
||||
|
||||
first.
|
||||
|
||||
----
|
||||
|
||||
## Simple one-line installer for Mac and Ubuntu
|
||||
## Simple One-Line Installer for Mac and Linux
|
||||
|
||||
```bash
|
||||
bash <(curl https://get.parity.io -L)
|
||||
@ -147,22 +107,49 @@ The one-line installer always defaults to the latest beta release. To install a
|
||||
bash <(curl https://get.parity.io -L) -r stable
|
||||
```
|
||||
|
||||
## Start Parity
|
||||
## Start Parity Ethereum
|
||||
|
||||
### Manually
|
||||
|
||||
To start Parity manually, just run
|
||||
To start Parity Ethereum manually, just run
|
||||
|
||||
```bash
|
||||
$ ./target/release/parity
|
||||
```
|
||||
|
||||
and Parity will begin syncing the Ethereum blockchain.
|
||||
so Parity Ethereum begins syncing the Ethereum blockchain.
|
||||
|
||||
### Using systemd service file
|
||||
### Using `systemd` service file
|
||||
|
||||
To start Parity as a regular user using systemd init:
|
||||
To start Parity Ethereum as a regular user using `systemd` init:
|
||||
|
||||
1. Copy `./scripts/parity.service` to your
|
||||
systemd user directory (usually `~/.config/systemd/user`).
|
||||
2. To configure Parity, write a `/etc/parity/config.toml` config file, see [Configuring Parity](https://paritytech.github.io/wiki/Configuring-Parity) for details.
|
||||
`systemd` user directory (usually `~/.config/systemd/user`).
|
||||
2. To configure Parity Ethereum, write a `/etc/parity/config.toml` config file, see [Configuring Parity Ethereum](https://paritytech.github.io/wiki/Configuring-Parity) for details.
|
||||
|
||||
## Parity Ethereum toolchain
|
||||
|
||||
In addition to the Parity Ethereum client, there are additional tools in this repository available:
|
||||
|
||||
- [evmbin](https://github.com/paritytech/parity-ethereum/blob/master/evmbin/) - EVM implementation for Parity Ethereum.
|
||||
- [ethabi](https://github.com/paritytech/ethabi) - Parity Ethereum function calls encoding.
|
||||
- [ethstore](https://github.com/paritytech/parity-ethereum/blob/master/ethstore/) - Parity Ethereum key management.
|
||||
- [ethkey](https://github.com/paritytech/parity-ethereum/blob/master/ethkey/) - Parity Ethereum keys generator.
|
||||
- [whisper](https://github.com/paritytech/parity-ethereum/blob/master/whisper/) - Implementation of Whisper-v2 PoC.
|
||||
|
||||
## Join the chat!
|
||||
|
||||
Questions? Get in touch with us on Gitter:
|
||||
[](https://gitter.im/paritytech/parity)
|
||||
[](https://gitter.im/paritytech/parity.js)
|
||||
[](https://gitter.im/paritytech/parity/miners)
|
||||
[](https://gitter.im/paritytech/parity-poa)
|
||||
|
||||
Alternatively, join our community on Matrix:
|
||||
[](https://riot.im/app/#/group/+parity:matrix.parity.io)
|
||||
|
||||
## Documentation
|
||||
|
||||
Official website: https://parity.io
|
||||
|
||||
Be sure to [check out our wiki](https://wiki.parity.io) for more information.
|
||||
|
@ -1,3 +0,0 @@
|
||||
Usage
|
||||
|
||||
```docker build -f docker/ubuntu/Dockerfile --tag ethcore/parity:branch_or_tag_name .```
|
@ -1,29 +0,0 @@
|
||||
FROM alpine:edge
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
# install tools and dependencies
|
||||
RUN apk add --no-cache gcc musl-dev pkgconfig g++ make curl \
|
||||
eudev-dev rust cargo git file binutils \
|
||||
libusb-dev linux-headers perl
|
||||
|
||||
# show backtraces
|
||||
ENV RUST_BACKTRACE 1
|
||||
|
||||
# show tools
|
||||
RUN rustc -vV && \
|
||||
cargo -V && \
|
||||
gcc -v &&\
|
||||
g++ -v
|
||||
|
||||
# build parity
|
||||
ADD . /build/parity
|
||||
RUN cd parity && \
|
||||
cargo build --release --verbose && \
|
||||
ls /build/parity/target/release/parity && \
|
||||
strip /build/parity/target/release/parity
|
||||
|
||||
RUN file /build/parity/target/release/parity
|
||||
|
||||
EXPOSE 8080 8545 8180
|
||||
ENTRYPOINT ["/build/parity/target/release/parity"]
|
@ -1,79 +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 OpenSSL for Android
|
||||
RUN cd /root && \
|
||||
git clone git://git.openssl.org/openssl.git && \
|
||||
cd openssl && \
|
||||
git checkout OpenSSL_1_1_0-stable
|
||||
ENV CROSS_SYSROOT /opt/ndk-standalone/sysroot
|
||||
RUN cd /root/openssl && \
|
||||
./Configure android-armeabi --cross-compile-prefix=arm-linux-androideabi- \
|
||||
-static no-stdio no-ui \
|
||||
-I/usr/local/android-ndk-r16b/sysroot/usr/include \
|
||||
-I/usr/local/android-ndk-r16b/sysroot/usr/include/arm-linux-androideabi \
|
||||
-L/usr/local/android-ndk-r16b/sysroot/usr/lib \
|
||||
--prefix=/opt/ndk-standalone/sysroot/usr
|
||||
RUN cd /root/openssl && \
|
||||
make build_libs && \
|
||||
make install_dev
|
||||
RUN rm -rf /root/openssl
|
||||
|
||||
# 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,36 +0,0 @@
|
||||
FROM centos:latest
|
||||
WORKDIR /build
|
||||
|
||||
# install tools and dependencies
|
||||
RUN yum -y update&& \
|
||||
yum install -y git make gcc-c++ gcc file binutils
|
||||
|
||||
# install rustup
|
||||
RUN curl -sSf https://static.rust-lang.org/rustup.sh -o rustup.sh &&\
|
||||
ls&&\
|
||||
sh rustup.sh --disable-sudo
|
||||
|
||||
# show backtraces
|
||||
ENV RUST_BACKTRACE 1
|
||||
|
||||
# set compiler
|
||||
ENV CXX g++
|
||||
ENV CC gcc
|
||||
|
||||
# show tools
|
||||
RUN rustc -vV && \
|
||||
cargo -V && \
|
||||
gcc -v &&\
|
||||
g++ -v
|
||||
|
||||
# build parity
|
||||
ADD . /build/parity
|
||||
RUN cd parity&&\
|
||||
cargo build --release --verbose && \
|
||||
ls /build/parity/target/release/parity && \
|
||||
strip /build/parity/target/release/parity
|
||||
|
||||
RUN file /build/parity/target/release/parity
|
||||
|
||||
EXPOSE 8080 8545 8180
|
||||
ENTRYPOINT ["/build/parity/target/release/parity"]
|
@ -1,66 +0,0 @@
|
||||
FROM ubuntu:14.04
|
||||
MAINTAINER Parity Technologies <devops@parity.io>
|
||||
WORKDIR /build
|
||||
#ENV for build TAG
|
||||
ARG BUILD_TAG
|
||||
ENV BUILD_TAG ${BUILD_TAG:-master}
|
||||
RUN echo "Build tag:" $BUILD_TAG
|
||||
# install tools and dependencies
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --force-yes --no-install-recommends \
|
||||
# make
|
||||
build-essential \
|
||||
# add-apt-repository
|
||||
software-properties-common \
|
||||
make \
|
||||
curl \
|
||||
wget \
|
||||
git \
|
||||
g++ \
|
||||
gcc \
|
||||
libc6 \
|
||||
libc6-dev \
|
||||
binutils \
|
||||
file \
|
||||
openssl \
|
||||
libssl-dev \
|
||||
libudev-dev \
|
||||
pkg-config \
|
||||
dpkg-dev \
|
||||
libudev-dev &&\
|
||||
# install rustup
|
||||
curl https://sh.rustup.rs -sSf | sh -s -- -y && \
|
||||
# rustup directory
|
||||
PATH=/root/.cargo/bin:$PATH && \
|
||||
# show backtraces
|
||||
RUST_BACKTRACE=1 && \
|
||||
# build parity
|
||||
cd /build&&git clone https://github.com/paritytech/parity && \
|
||||
cd parity && \
|
||||
git pull&& \
|
||||
git checkout $BUILD_TAG && \
|
||||
cargo build --verbose --release --features final && \
|
||||
#ls /build/parity/target/release/parity && \
|
||||
strip /build/parity/target/release/parity && \
|
||||
file /build/parity/target/release/parity&&mkdir -p /parity&& cp /build/parity/target/release/parity /parity&&\
|
||||
#cleanup Docker image
|
||||
rm -rf /root/.cargo&&rm -rf /root/.multirust&&rm -rf /root/.rustup&&rm -rf /build&&\
|
||||
apt-get purge -y \
|
||||
# make
|
||||
build-essential \
|
||||
# add-apt-repository
|
||||
software-properties-common \
|
||||
make \
|
||||
curl \
|
||||
wget \
|
||||
git \
|
||||
g++ \
|
||||
gcc \
|
||||
binutils \
|
||||
file \
|
||||
pkg-config \
|
||||
dpkg-dev &&\
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
# setup ENTRYPOINT
|
||||
EXPOSE 8080 8545 8180
|
||||
ENTRYPOINT ["/parity/parity"]
|
@ -1,42 +0,0 @@
|
||||
FROM ubuntu:14.04
|
||||
WORKDIR /build
|
||||
|
||||
# install tools and dependencies
|
||||
RUN apt-get update && \
|
||||
apt-get install -y \
|
||||
g++ \
|
||||
build-essential \
|
||||
curl \
|
||||
git \
|
||||
file \
|
||||
binutils \
|
||||
libssl-dev \
|
||||
pkg-config \
|
||||
libudev-dev
|
||||
|
||||
# install rustup
|
||||
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y
|
||||
|
||||
# rustup directory
|
||||
ENV PATH /root/.cargo/bin:$PATH
|
||||
|
||||
# show backtraces
|
||||
ENV RUST_BACKTRACE 1
|
||||
|
||||
# show tools
|
||||
RUN rustc -vV && \
|
||||
cargo -V && \
|
||||
gcc -v &&\
|
||||
g++ -v
|
||||
|
||||
# build parity
|
||||
ADD . /build/parity
|
||||
RUN cd parity && \
|
||||
cargo build --release --verbose && \
|
||||
ls /build/parity/target/release/parity && \
|
||||
strip /build/parity/target/release/parity
|
||||
|
||||
RUN file /build/parity/target/release/parity
|
||||
|
||||
EXPOSE 8080 8545 8180
|
||||
ENTRYPOINT ["/build/parity/target/release/parity"]
|
@ -6,13 +6,14 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
[lib]
|
||||
|
||||
[dependencies]
|
||||
log = "0.3"
|
||||
keccak-hash = { git = "https://github.com/paritytech/parity-common" }
|
||||
primal = "0.2.3"
|
||||
parking_lot = "0.6"
|
||||
crunchy = "0.1.0"
|
||||
memmap = "0.6"
|
||||
either = "1.0.0"
|
||||
ethereum-types = "0.3"
|
||||
keccak-hash = { git = "https://github.com/paritytech/parity-common" }
|
||||
log = "0.4"
|
||||
memmap = "0.6"
|
||||
parking_lot = "0.6"
|
||||
primal = "0.2.3"
|
||||
|
||||
[dev-dependencies]
|
||||
tempdir = "0.3"
|
||||
|
@ -16,10 +16,11 @@
|
||||
|
||||
#![cfg_attr(feature = "benches", feature(test))]
|
||||
|
||||
extern crate primal;
|
||||
extern crate parking_lot;
|
||||
extern crate either;
|
||||
extern crate ethereum_types;
|
||||
extern crate memmap;
|
||||
extern crate parking_lot;
|
||||
extern crate primal;
|
||||
|
||||
#[macro_use]
|
||||
extern crate crunchy;
|
||||
@ -38,6 +39,7 @@ mod shared;
|
||||
pub use cache::{NodeCacheBuilder, OptimizeFor};
|
||||
pub use compute::{ProofOfWork, quick_get_difficulty, slow_hash_block_number};
|
||||
use compute::Light;
|
||||
use ethereum_types::{U256, U512};
|
||||
use keccak::H256;
|
||||
use parking_lot::Mutex;
|
||||
pub use seed_compute::SeedHashCompute;
|
||||
@ -136,6 +138,29 @@ impl EthashManager {
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert an Ethash boundary to its original difficulty. Basically just `f(x) = 2^256 / x`.
|
||||
pub fn boundary_to_difficulty(boundary: ðereum_types::H256) -> U256 {
|
||||
difficulty_to_boundary_aux(&**boundary)
|
||||
}
|
||||
|
||||
/// Convert an Ethash difficulty to the target boundary. Basically just `f(x) = 2^256 / x`.
|
||||
pub fn difficulty_to_boundary(difficulty: &U256) -> ethereum_types::H256 {
|
||||
difficulty_to_boundary_aux(difficulty).into()
|
||||
}
|
||||
|
||||
fn difficulty_to_boundary_aux<T: Into<U512>>(difficulty: T) -> ethereum_types::U256 {
|
||||
let difficulty = difficulty.into();
|
||||
|
||||
assert!(!difficulty.is_zero());
|
||||
|
||||
if difficulty == U512::one() {
|
||||
U256::max_value()
|
||||
} else {
|
||||
// difficulty > 1, so result should never overflow 256 bits
|
||||
U256::from((U512::one() << 256) / difficulty)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lru() {
|
||||
use tempdir::TempDir;
|
||||
@ -155,6 +180,43 @@ fn test_lru() {
|
||||
assert_eq!(ethash.cache.lock().prev_epoch.unwrap(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_difficulty_to_boundary() {
|
||||
use ethereum_types::H256;
|
||||
use std::str::FromStr;
|
||||
|
||||
assert_eq!(difficulty_to_boundary(&U256::from(1)), H256::from(U256::max_value()));
|
||||
assert_eq!(difficulty_to_boundary(&U256::from(2)), H256::from_str("8000000000000000000000000000000000000000000000000000000000000000").unwrap());
|
||||
assert_eq!(difficulty_to_boundary(&U256::from(4)), H256::from_str("4000000000000000000000000000000000000000000000000000000000000000").unwrap());
|
||||
assert_eq!(difficulty_to_boundary(&U256::from(32)), H256::from_str("0800000000000000000000000000000000000000000000000000000000000000").unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_difficulty_to_boundary_regression() {
|
||||
use ethereum_types::H256;
|
||||
|
||||
// the last bit was originally being truncated when performing the conversion
|
||||
// https://github.com/paritytech/parity-ethereum/issues/8397
|
||||
for difficulty in 1..9 {
|
||||
assert_eq!(U256::from(difficulty), boundary_to_difficulty(&difficulty_to_boundary(&difficulty.into())));
|
||||
assert_eq!(H256::from(difficulty), difficulty_to_boundary(&boundary_to_difficulty(&difficulty.into())));
|
||||
assert_eq!(U256::from(difficulty), boundary_to_difficulty(&boundary_to_difficulty(&difficulty.into()).into()));
|
||||
assert_eq!(H256::from(difficulty), difficulty_to_boundary(&difficulty_to_boundary(&difficulty.into()).into()));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_difficulty_to_boundary_panics_on_zero() {
|
||||
difficulty_to_boundary(&U256::from(0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_boundary_to_difficulty_panics_on_zero() {
|
||||
boundary_to_difficulty(ðereum_types::H256::from(0));
|
||||
}
|
||||
|
||||
#[cfg(feature = "benches")]
|
||||
mod benchmarks {
|
||||
extern crate test;
|
||||
|
@ -80,6 +80,17 @@ tempdir = "0.3"
|
||||
trie-standardmap = { git = "https://github.com/paritytech/parity-common" }
|
||||
|
||||
[features]
|
||||
parity = ["work-notify", "price-info", "stratum"]
|
||||
# Large optional features that are enabled by default for Parity,
|
||||
# but might be omitted for other dependent crates.
|
||||
work-notify = ["ethcore-miner/work-notify"]
|
||||
price-info = ["ethcore-miner/price-info"]
|
||||
stratum = ["ethcore-stratum"]
|
||||
|
||||
# Disables seal verification for mined blocks.
|
||||
# This allows you to submit any seal via RPC to test and benchmark
|
||||
# how fast pending block get's created while running on the mainnet.
|
||||
miner-debug = []
|
||||
# Display EVM debug traces.
|
||||
evm-debug = ["evm/evm-debug"]
|
||||
# Display EVM debug traces when running tests.
|
||||
@ -91,12 +102,11 @@ 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
|
||||
benches = []
|
||||
# Compile test helpers
|
||||
test-helpers = ["tempdir"]
|
||||
work-notify = ["ethcore-miner/work-notify"]
|
||||
price-info = ["ethcore-miner/price-info"]
|
||||
stratum = ["ethcore-stratum"]
|
||||
|
@ -16,17 +16,16 @@
|
||||
|
||||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
extern crate ethcore_util as util;
|
||||
extern crate rand;
|
||||
extern crate bn;
|
||||
extern crate parity_crypto;
|
||||
extern crate ethereum_types;
|
||||
extern crate ethkey;
|
||||
extern crate parity_crypto;
|
||||
extern crate rand;
|
||||
extern crate rustc_hex;
|
||||
extern crate ethcore_bigint;
|
||||
extern crate test;
|
||||
|
||||
use self::test::{Bencher};
|
||||
use rand::{StdRng};
|
||||
use self::test::Bencher;
|
||||
use rand::StdRng;
|
||||
|
||||
#[bench]
|
||||
fn bn_128_pairing(b: &mut Bencher) {
|
||||
@ -62,8 +61,7 @@ fn bn_128_mul(b: &mut Bencher) {
|
||||
fn sha256(b: &mut Bencher) {
|
||||
use parity_crypto::digest::sha256;
|
||||
|
||||
let mut input: [u8; 256] = [0; 256];
|
||||
let mut out = [0; 32];
|
||||
let input = [0_u8; 256];
|
||||
|
||||
b.iter(|| {
|
||||
sha256(&input);
|
||||
@ -74,7 +72,7 @@ fn sha256(b: &mut Bencher) {
|
||||
fn ecrecover(b: &mut Bencher) {
|
||||
use rustc_hex::FromHex;
|
||||
use ethkey::{Signature, recover as ec_recover};
|
||||
use ethcore_bigint::hash::H256;
|
||||
use ethereum_types::H256;
|
||||
let input = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b650acf9d3f5f0a2c799776a1254355d5f4061762a237396a99a0e0e3fc2bcd6729514a0dacb2e623ac4abd157cb18163ff942280db4d5caad66ddf941ba12e03").unwrap();
|
||||
let hash = H256::from_slice(&input[0..32]);
|
||||
let v = H256::from_slice(&input[32..64]);
|
||||
|
@ -57,7 +57,7 @@ impl Finalize for Result<GasLeft> {
|
||||
|
||||
/// 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>
|
||||
+ 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`
|
||||
|
@ -134,6 +134,8 @@ enum_with_from_u8! {
|
||||
RETURNDATASIZE = 0x3d,
|
||||
#[doc = "copy return data buffer to memory"]
|
||||
RETURNDATACOPY = 0x3e,
|
||||
#[doc = "return the keccak256 hash of contract code"]
|
||||
EXTCODEHASH = 0x3f,
|
||||
|
||||
#[doc = "get hash of most recent complete block"]
|
||||
BLOCKHASH = 0x40,
|
||||
@ -326,7 +328,7 @@ enum_with_from_u8! {
|
||||
#[doc = "like CALLCODE but keeps caller's value and sender"]
|
||||
DELEGATECALL = 0xf4,
|
||||
#[doc = "create a new account and set creation address to sha3(sender + sha3(init code)) % 2**160"]
|
||||
CREATE2 = 0xfb,
|
||||
CREATE2 = 0xf5,
|
||||
#[doc = "stop execution and revert state changes. Return output data."]
|
||||
REVERT = 0xfd,
|
||||
#[doc = "like CALL but it does not take value, nor modify the state"]
|
||||
@ -492,6 +494,7 @@ lazy_static! {
|
||||
arr[CALLDATALOAD as usize] = Some(InstructionInfo::new("CALLDATALOAD", 1, 1, GasPriceTier::VeryLow));
|
||||
arr[CALLDATASIZE as usize] = Some(InstructionInfo::new("CALLDATASIZE", 0, 1, GasPriceTier::Base));
|
||||
arr[CALLDATACOPY as usize] = Some(InstructionInfo::new("CALLDATACOPY", 3, 0, GasPriceTier::VeryLow));
|
||||
arr[EXTCODEHASH as usize] = Some(InstructionInfo::new("EXTCODEHASH", 1, 1, GasPriceTier::Special));
|
||||
arr[CODESIZE as usize] = Some(InstructionInfo::new("CODESIZE", 0, 1, GasPriceTier::Base));
|
||||
arr[CODECOPY as usize] = Some(InstructionInfo::new("CODECOPY", 3, 0, GasPriceTier::VeryLow));
|
||||
arr[GASPRICE as usize] = Some(InstructionInfo::new("GASPRICE", 0, 1, GasPriceTier::Base));
|
||||
@ -591,7 +594,7 @@ lazy_static! {
|
||||
arr[DELEGATECALL as usize] = Some(InstructionInfo::new("DELEGATECALL", 6, 1, GasPriceTier::Special));
|
||||
arr[STATICCALL as usize] = Some(InstructionInfo::new("STATICCALL", 6, 1, GasPriceTier::Special));
|
||||
arr[SUICIDE as usize] = Some(InstructionInfo::new("SUICIDE", 1, 0, GasPriceTier::Special));
|
||||
arr[CREATE2 as usize] = Some(InstructionInfo::new("CREATE2", 3, 1, GasPriceTier::Special));
|
||||
arr[CREATE2 as usize] = Some(InstructionInfo::new("CREATE2", 4, 1, GasPriceTier::Special));
|
||||
arr[REVERT as usize] = Some(InstructionInfo::new("REVERT", 2, 0, GasPriceTier::Zero));
|
||||
arr
|
||||
};
|
||||
|
@ -125,12 +125,17 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
|
||||
let newval = stack.peek(1);
|
||||
let val = U256::from(&*ext.storage_at(&address)?);
|
||||
|
||||
let gas = if val.is_zero() && !newval.is_zero() {
|
||||
schedule.sstore_set_gas
|
||||
let gas = if schedule.eip1283 {
|
||||
let orig = U256::from(&*ext.initial_storage_at(&address)?);
|
||||
calculate_eip1283_sstore_gas(schedule, &orig, &val, &newval)
|
||||
} else {
|
||||
// Refund for below case is added when actually executing sstore
|
||||
// !is_zero(&val) && is_zero(newval)
|
||||
schedule.sstore_reset_gas
|
||||
if val.is_zero() && !newval.is_zero() {
|
||||
schedule.sstore_set_gas
|
||||
} else {
|
||||
// Refund for below case is added when actually executing sstore
|
||||
// !is_zero(&val) && is_zero(newval)
|
||||
schedule.sstore_reset_gas
|
||||
}
|
||||
};
|
||||
Request::Gas(Gas::from(gas))
|
||||
},
|
||||
@ -143,6 +148,9 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
|
||||
instructions::EXTCODESIZE => {
|
||||
Request::Gas(Gas::from(schedule.extcodesize_gas))
|
||||
},
|
||||
instructions::EXTCODEHASH => {
|
||||
Request::Gas(Gas::from(schedule.extcodehash_gas))
|
||||
},
|
||||
instructions::SUICIDE => {
|
||||
let mut gas = Gas::from(schedule.suicide_gas);
|
||||
|
||||
@ -168,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 => {
|
||||
@ -223,9 +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 = mem_needed(stack.peek(1), stack.peek(2))?;
|
||||
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)
|
||||
},
|
||||
@ -275,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));
|
||||
|
||||
@ -303,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)?;
|
||||
@ -335,6 +357,99 @@ 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(
|
||||
if current == new {
|
||||
// 1. If current value equals new value (this is a no-op), 200 gas is deducted.
|
||||
schedule.sload_gas
|
||||
} else {
|
||||
// 2. If current value does not equal new value
|
||||
if original == current {
|
||||
// 2.1. If original value equals current value (this storage slot has not been changed by the current execution context)
|
||||
if original.is_zero() {
|
||||
// 2.1.1. If original value is 0, 20000 gas is deducted.
|
||||
schedule.sstore_set_gas
|
||||
} else {
|
||||
// 2.1.2. Otherwise, 5000 gas is deducted.
|
||||
schedule.sstore_reset_gas
|
||||
|
||||
// 2.1.2.1. If new value is 0, add 15000 gas to refund counter.
|
||||
}
|
||||
} else {
|
||||
// 2.2. If original value does not equal current value (this storage slot is dirty), 200 gas is deducted. Apply both of the following clauses.
|
||||
schedule.sload_gas
|
||||
|
||||
// 2.2.1. If original value is not 0
|
||||
// 2.2.1.1. If current value is 0 (also means that new value is not 0), remove 15000 gas from refund counter. We can prove that refund counter will never go below 0.
|
||||
// 2.2.1.2. If new value is 0 (also means that current value is not 0), add 15000 gas to refund counter.
|
||||
|
||||
// 2.2.2. If original value equals new value (this storage slot is reset)
|
||||
// 2.2.2.1. If original value is 0, add 19800 gas to refund counter.
|
||||
// 2.2.2.2. Otherwise, add 4800 gas to refund counter.
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
pub fn handle_eip1283_sstore_clears_refund(ext: &mut vm::Ext, original: &U256, current: &U256, new: &U256) {
|
||||
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.
|
||||
} else {
|
||||
// 2. If current value does not equal new value
|
||||
if original == current {
|
||||
// 2.1. If original value equals current value (this storage slot has not been changed by the current execution context)
|
||||
if original.is_zero() {
|
||||
// 2.1.1. If original value is 0, 20000 gas is deducted.
|
||||
} else {
|
||||
// 2.1.2. Otherwise, 5000 gas is deducted.
|
||||
if new.is_zero() {
|
||||
// 2.1.2.1. If new value is 0, add 15000 gas to refund counter.
|
||||
ext.add_sstore_refund(sstore_clears_schedule);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 2.2. If original value does not equal current value (this storage slot is dirty), 200 gas is deducted. Apply both of the following clauses.
|
||||
|
||||
if !original.is_zero() {
|
||||
// 2.2.1. If original value is not 0
|
||||
if current.is_zero() {
|
||||
// 2.2.1.1. If current value is 0 (also means that new value is not 0), remove 15000 gas from refund counter. We can prove that refund counter will never go below 0.
|
||||
ext.sub_sstore_refund(sstore_clears_schedule);
|
||||
} else if new.is_zero() {
|
||||
// 2.2.1.2. If new value is 0 (also means that current value is not 0), add 15000 gas to refund counter.
|
||||
ext.add_sstore_refund(sstore_clears_schedule);
|
||||
}
|
||||
}
|
||||
|
||||
if original == new {
|
||||
// 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 = 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 = ext.schedule().sstore_reset_gas - ext.schedule().sload_gas;
|
||||
ext.add_sstore_refund(refund);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mem_gas_cost() {
|
||||
// given
|
||||
|
@ -186,8 +186,7 @@ impl<Cost: CostType> vm::Vm for Interpreter<Cost> {
|
||||
match result {
|
||||
InstructionResult::JumpToPosition(position) => {
|
||||
if valid_jump_destinations.is_none() {
|
||||
let code_hash = params.code_hash.clone().unwrap_or_else(|| keccak(code.as_ref()));
|
||||
valid_jump_destinations = Some(self.cache.jump_destinations(&code_hash, code));
|
||||
valid_jump_destinations = Some(self.cache.jump_destinations(¶ms.code_hash, code));
|
||||
}
|
||||
let jump_destinations = valid_jump_destinations.as_ref().expect("jump_destinations are initialized on first jump; qed");
|
||||
let pos = self.verify_jump(position, jump_destinations)?;
|
||||
@ -230,8 +229,9 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
(instruction == instructions::STATICCALL && !schedule.have_static_call) ||
|
||||
((instruction == instructions::RETURNDATACOPY || instruction == instructions::RETURNDATASIZE) && !schedule.have_return_data) ||
|
||||
(instruction == instructions::REVERT && !schedule.have_revert) ||
|
||||
((instruction == instructions::SHL || instruction == instructions::SHR || instruction == instructions::SAR) && !schedule.have_bitwise_shifting) {
|
||||
|
||||
((instruction == instructions::SHL || instruction == instructions::SHR || instruction == instructions::SAR) && !schedule.have_bitwise_shifting) ||
|
||||
(instruction == instructions::EXTCODEHASH && !schedule.have_extcodehash)
|
||||
{
|
||||
return Err(vm::Error::BadInstruction {
|
||||
instruction: instruction as u8
|
||||
});
|
||||
@ -318,6 +318,11 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
let endowment = stack.pop_back();
|
||||
let init_off = stack.pop_back();
|
||||
let init_size = stack.pop_back();
|
||||
let address_scheme = match instruction {
|
||||
instructions::CREATE => CreateContractAddress::FromSenderAndNonce,
|
||||
instructions::CREATE2 => CreateContractAddress::FromSenderSaltAndCodeHash(stack.pop_back().into()),
|
||||
_ => unreachable!("instruction can only be CREATE/CREATE2 checked above; qed"),
|
||||
};
|
||||
|
||||
let create_gas = provided.expect("`provided` comes through Self::exec from `Gasometer::get_gas_cost_mem`; `gas_gas_mem_cost` guarantees `Some` when instruction is `CALL`/`CALLCODE`/`DELEGATECALL`/`CREATE`; this is `CREATE`; qed");
|
||||
|
||||
@ -335,7 +340,6 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
}
|
||||
|
||||
let contract_code = self.mem.read_slice(init_off, init_size);
|
||||
let address_scheme = if instruction == instructions::CREATE { CreateContractAddress::FromSenderAndNonce } else { CreateContractAddress::FromSenderAndCodeHash };
|
||||
|
||||
let create_result = ext.create(&create_gas.as_u256(), &endowment, contract_code, address_scheme);
|
||||
return match create_result {
|
||||
@ -510,8 +514,14 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
|
||||
let current_val = U256::from(&*ext.storage_at(&address)?);
|
||||
// Increase refund for clear
|
||||
if !self.is_zero(¤t_val) && self.is_zero(&val) {
|
||||
ext.inc_sstore_clears();
|
||||
if ext.schedule().eip1283 {
|
||||
let original_val = U256::from(&*ext.initial_storage_at(&address)?);
|
||||
gasometer::handle_eip1283_sstore_clears_refund(ext, &original_val, ¤t_val, &val);
|
||||
} else {
|
||||
if !current_val.is_zero() && val.is_zero() {
|
||||
let sstore_clears_schedule = ext.schedule().sstore_refund_gas;
|
||||
ext.add_sstore_refund(sstore_clears_schedule);
|
||||
}
|
||||
}
|
||||
ext.set_storage(address, H256::from(&val))?;
|
||||
},
|
||||
@ -568,9 +578,14 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
},
|
||||
instructions::EXTCODESIZE => {
|
||||
let address = u256_to_address(&stack.pop_back());
|
||||
let len = ext.extcodesize(&address)?;
|
||||
let len = ext.extcodesize(&address)?.unwrap_or(0);
|
||||
stack.push(U256::from(len));
|
||||
},
|
||||
instructions::EXTCODEHASH => {
|
||||
let address = u256_to_address(&stack.pop_back());
|
||||
let hash = ext.extcodehash(&address)?.unwrap_or_else(H256::zero);
|
||||
stack.push(U256::from(hash));
|
||||
},
|
||||
instructions::CALLDATACOPY => {
|
||||
Self::copy_data_to_memory(&mut self.mem, stack, params.data.as_ref().map_or_else(|| &[] as &[u8], |d| &*d as &[u8]));
|
||||
},
|
||||
@ -591,7 +606,11 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
instructions::EXTCODECOPY => {
|
||||
let address = u256_to_address(&stack.pop_back());
|
||||
let code = ext.extcode(&address)?;
|
||||
Self::copy_data_to_memory(&mut self.mem, stack, &code);
|
||||
Self::copy_data_to_memory(
|
||||
&mut self.mem,
|
||||
stack,
|
||||
code.as_ref().map(|c| &(*c)[..]).unwrap_or(&[])
|
||||
);
|
||||
},
|
||||
instructions::GASPRICE => {
|
||||
stack.push(params.gas_price.clone());
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -716,7 +716,7 @@ fn test_jumps(factory: super::Factory) {
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(ext.sstore_clears, 1);
|
||||
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));
|
||||
@ -746,6 +746,7 @@ fn test_calls(factory: super::Factory) {
|
||||
|
||||
assert_set_contains(&ext.calls, &FakeCall {
|
||||
call_type: FakeCallType::Call,
|
||||
create_scheme: None,
|
||||
gas: U256::from(2556),
|
||||
sender_address: Some(address.clone()),
|
||||
receive_address: Some(code_address.clone()),
|
||||
@ -755,6 +756,7 @@ fn test_calls(factory: super::Factory) {
|
||||
});
|
||||
assert_set_contains(&ext.calls, &FakeCall {
|
||||
call_type: FakeCallType::Call,
|
||||
create_scheme: None,
|
||||
gas: U256::from(2556),
|
||||
sender_address: Some(address.clone()),
|
||||
receive_address: Some(address.clone()),
|
||||
|
@ -127,9 +127,6 @@ pub trait LightChainClient: Send + Sync {
|
||||
/// Get the `i`th CHT root.
|
||||
fn cht_root(&self, i: usize) -> Option<H256>;
|
||||
|
||||
/// Get the EIP-86 transition block number.
|
||||
fn eip86_transition(&self) -> BlockNumber;
|
||||
|
||||
/// Get a report of import activity since the last call.
|
||||
fn report(&self) -> ClientReport;
|
||||
}
|
||||
@ -585,10 +582,6 @@ impl<T: ChainDataFetcher> LightChainClient for Client<T> {
|
||||
Client::cht_root(self, i)
|
||||
}
|
||||
|
||||
fn eip86_transition(&self) -> BlockNumber {
|
||||
self.engine().params().eip86_transition
|
||||
}
|
||||
|
||||
fn report(&self) -> ClientReport {
|
||||
Client::report(self)
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ pub mod provider;
|
||||
mod types;
|
||||
|
||||
pub use self::cache::Cache;
|
||||
pub use self::provider::Provider;
|
||||
pub use self::provider::{Provider, MAX_HEADERS_PER_REQUEST};
|
||||
pub use self::transaction_queue::TransactionQueue;
|
||||
pub use types::request as request;
|
||||
|
||||
|
@ -70,9 +70,6 @@ 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);
|
||||
|
||||
/// Max number of transactions in a single packet.
|
||||
const MAX_TRANSACTIONS_TO_PROPAGATE: usize = 64;
|
||||
|
||||
// minimum interval between updates.
|
||||
const UPDATE_INTERVAL: Duration = Duration::from_millis(5000);
|
||||
|
||||
@ -648,7 +645,7 @@ impl LightProtocol {
|
||||
fn propagate_transactions(&self, io: &IoContext) {
|
||||
if self.capabilities.read().tx_relay { return }
|
||||
|
||||
let ready_transactions = self.provider.ready_transactions(MAX_TRANSACTIONS_TO_PROPAGATE);
|
||||
let ready_transactions = self.provider.transactions_to_propagate();
|
||||
if ready_transactions.is_empty() { return }
|
||||
|
||||
trace!(target: "pip", "propagate transactions: {} ready", ready_transactions.len());
|
||||
|
@ -171,8 +171,8 @@ impl Provider for TestProvider {
|
||||
})
|
||||
}
|
||||
|
||||
fn ready_transactions(&self, max_len: usize) -> Vec<PendingTransaction> {
|
||||
self.0.client.ready_transactions(max_len)
|
||||
fn transactions_to_propagate(&self) -> Vec<PendingTransaction> {
|
||||
self.0.client.transactions_to_propagate()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,6 +204,8 @@ fn guess_capabilities(requests: &[CheckedRequest]) -> Capabilities {
|
||||
caps.serve_headers = true,
|
||||
CheckedRequest::HeaderByHash(_, _) =>
|
||||
caps.serve_headers = true,
|
||||
CheckedRequest::HeaderWithAncestors(_, _) =>
|
||||
caps.serve_headers = true,
|
||||
CheckedRequest::TransactionIndex(_, _) => {} // hashes yield no info.
|
||||
CheckedRequest::Signal(_, _) =>
|
||||
caps.serve_headers = true,
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
//! Request types, verification, and verification errors.
|
||||
|
||||
use std::cmp;
|
||||
use std::sync::Arc;
|
||||
|
||||
use bytes::Bytes;
|
||||
@ -47,6 +48,8 @@ pub enum Request {
|
||||
HeaderProof(HeaderProof),
|
||||
/// A request for a header by hash.
|
||||
HeaderByHash(HeaderByHash),
|
||||
/// A request for a header by hash with a range of its ancestors.
|
||||
HeaderWithAncestors(HeaderWithAncestors),
|
||||
/// A request for the index of a transaction.
|
||||
TransactionIndex(TransactionIndex),
|
||||
/// A request for block receipts.
|
||||
@ -136,6 +139,7 @@ macro_rules! impl_single {
|
||||
// implement traits for each kind of request.
|
||||
impl_single!(HeaderProof, HeaderProof, (H256, U256));
|
||||
impl_single!(HeaderByHash, HeaderByHash, encoded::Header);
|
||||
impl_single!(HeaderWithAncestors, HeaderWithAncestors, Vec<encoded::Header>);
|
||||
impl_single!(TransactionIndex, TransactionIndex, net_request::TransactionIndexResponse);
|
||||
impl_single!(Receipts, BlockReceipts, Vec<Receipt>);
|
||||
impl_single!(Body, Body, encoded::Block);
|
||||
@ -246,6 +250,7 @@ impl From<encoded::Header> for HeaderRef {
|
||||
pub enum CheckedRequest {
|
||||
HeaderProof(HeaderProof, net_request::IncompleteHeaderProofRequest),
|
||||
HeaderByHash(HeaderByHash, net_request::IncompleteHeadersRequest),
|
||||
HeaderWithAncestors(HeaderWithAncestors, net_request::IncompleteHeadersRequest),
|
||||
TransactionIndex(TransactionIndex, net_request::IncompleteTransactionIndexRequest),
|
||||
Receipts(BlockReceipts, net_request::IncompleteReceiptsRequest),
|
||||
Body(Body, net_request::IncompleteBodyRequest),
|
||||
@ -267,6 +272,16 @@ impl From<Request> for CheckedRequest {
|
||||
};
|
||||
CheckedRequest::HeaderByHash(req, net_req)
|
||||
}
|
||||
Request::HeaderWithAncestors(req) => {
|
||||
let net_req = net_request::IncompleteHeadersRequest {
|
||||
start: req.block_hash.map(Into::into),
|
||||
skip: 0,
|
||||
max: req.ancestor_count + 1,
|
||||
reverse: true,
|
||||
};
|
||||
trace!(target: "on_demand", "HeaderWithAncestors Request, {:?}", net_req);
|
||||
CheckedRequest::HeaderWithAncestors(req, net_req)
|
||||
}
|
||||
Request::HeaderProof(req) => {
|
||||
let net_req = net_request::IncompleteHeaderProofRequest {
|
||||
num: req.num().into(),
|
||||
@ -335,6 +350,7 @@ impl CheckedRequest {
|
||||
match self {
|
||||
CheckedRequest::HeaderProof(_, req) => NetRequest::HeaderProof(req),
|
||||
CheckedRequest::HeaderByHash(_, req) => NetRequest::Headers(req),
|
||||
CheckedRequest::HeaderWithAncestors(_, req) => NetRequest::Headers(req),
|
||||
CheckedRequest::TransactionIndex(_, req) => NetRequest::TransactionIndex(req),
|
||||
CheckedRequest::Receipts(_, req) => NetRequest::Receipts(req),
|
||||
CheckedRequest::Body(_, req) => NetRequest::Body(req),
|
||||
@ -390,6 +406,27 @@ impl CheckedRequest {
|
||||
|
||||
None
|
||||
}
|
||||
CheckedRequest::HeaderWithAncestors(_, ref req) => {
|
||||
if req.skip != 1 || !req.reverse {
|
||||
return None;
|
||||
}
|
||||
|
||||
if let Some(&net_request::HashOrNumber::Hash(start)) = req.start.as_ref() {
|
||||
let mut result = Vec::with_capacity(req.max as usize);
|
||||
let mut hash = start;
|
||||
let mut cache = cache.lock();
|
||||
for _ in 0..req.max {
|
||||
match cache.block_header(&hash) {
|
||||
Some(header) => {
|
||||
hash = header.parent_hash();
|
||||
result.push(header);
|
||||
}
|
||||
None => return None,
|
||||
}
|
||||
}
|
||||
Some(Response::HeaderWithAncestors(result))
|
||||
} else { None }
|
||||
}
|
||||
CheckedRequest::Receipts(ref check, ref req) => {
|
||||
// empty transactions -> no receipts
|
||||
if check.0.as_ref().ok().map_or(false, |hdr| hdr.receipts_root() == KECCAK_NULL_RLP) {
|
||||
@ -458,6 +495,7 @@ macro_rules! match_me {
|
||||
match $me {
|
||||
CheckedRequest::HeaderProof($check, $req) => $e,
|
||||
CheckedRequest::HeaderByHash($check, $req) => $e,
|
||||
CheckedRequest::HeaderWithAncestors($check, $req) => $e,
|
||||
CheckedRequest::TransactionIndex($check, $req) => $e,
|
||||
CheckedRequest::Receipts($check, $req) => $e,
|
||||
CheckedRequest::Body($check, $req) => $e,
|
||||
@ -487,6 +525,15 @@ impl IncompleteRequest for CheckedRequest {
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
CheckedRequest::HeaderWithAncestors(ref check, ref req) => {
|
||||
req.check_outputs(&mut f)?;
|
||||
|
||||
// make sure the output given is definitively a hash.
|
||||
match check.block_hash {
|
||||
Field::BackReference(r, idx) => f(r, idx, OutputKind::Hash),
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
CheckedRequest::TransactionIndex(_, ref req) => req.check_outputs(f),
|
||||
CheckedRequest::Receipts(_, ref req) => req.check_outputs(f),
|
||||
CheckedRequest::Body(_, ref req) => req.check_outputs(f),
|
||||
@ -507,15 +554,46 @@ impl IncompleteRequest for CheckedRequest {
|
||||
|
||||
fn complete(self) -> Result<Self::Complete, net_request::NoSuchOutput> {
|
||||
match self {
|
||||
CheckedRequest::HeaderProof(_, req) => req.complete().map(CompleteRequest::HeaderProof),
|
||||
CheckedRequest::HeaderByHash(_, req) => req.complete().map(CompleteRequest::Headers),
|
||||
CheckedRequest::TransactionIndex(_, req) => req.complete().map(CompleteRequest::TransactionIndex),
|
||||
CheckedRequest::Receipts(_, req) => req.complete().map(CompleteRequest::Receipts),
|
||||
CheckedRequest::Body(_, req) => req.complete().map(CompleteRequest::Body),
|
||||
CheckedRequest::Account(_, req) => req.complete().map(CompleteRequest::Account),
|
||||
CheckedRequest::Code(_, req) => req.complete().map(CompleteRequest::Code),
|
||||
CheckedRequest::Execution(_, req) => req.complete().map(CompleteRequest::Execution),
|
||||
CheckedRequest::Signal(_, req) => req.complete().map(CompleteRequest::Signal),
|
||||
CheckedRequest::HeaderProof(_, req) => {
|
||||
trace!(target: "on_demand", "HeaderProof request completed {:?}", req);
|
||||
req.complete().map(CompleteRequest::HeaderProof)
|
||||
}
|
||||
CheckedRequest::HeaderByHash(_, req) => {
|
||||
trace!(target: "on_demand", "HeaderByHash request completed {:?}", req);
|
||||
req.complete().map(CompleteRequest::Headers)
|
||||
}
|
||||
CheckedRequest::HeaderWithAncestors(_, req) => {
|
||||
trace!(target: "on_demand", "HeaderWithAncestors request completed {:?}", req);
|
||||
req.complete().map(CompleteRequest::Headers)
|
||||
}
|
||||
CheckedRequest::TransactionIndex(_, req) => {
|
||||
trace!(target: "on_demand", "TransactionIndex request completed {:?}", req);
|
||||
req.complete().map(CompleteRequest::TransactionIndex)
|
||||
}
|
||||
CheckedRequest::Receipts(_, req) => {
|
||||
trace!(target: "on_demand", "Receipt request completed {:?}", req);
|
||||
req.complete().map(CompleteRequest::Receipts)
|
||||
}
|
||||
CheckedRequest::Body(_, req) => {
|
||||
trace!(target: "on_demand", "Block request completed {:?}", req);
|
||||
req.complete().map(CompleteRequest::Body)
|
||||
}
|
||||
CheckedRequest::Account(_, req) => {
|
||||
trace!(target: "on_demand", "Account request completed {:?}", req);
|
||||
req.complete().map(CompleteRequest::Account)
|
||||
}
|
||||
CheckedRequest::Code(_, req) => {
|
||||
trace!(target: "on_demand", "Code request completed {:?}", req);
|
||||
req.complete().map(CompleteRequest::Code)
|
||||
}
|
||||
CheckedRequest::Execution(_, req) => {
|
||||
trace!(target: "on_demand", "Execution request completed {:?}", req);
|
||||
req.complete().map(CompleteRequest::Execution)
|
||||
}
|
||||
CheckedRequest::Signal(_, req) => {
|
||||
trace!(target: "on_demand", "Signal request completed {:?}", req);
|
||||
req.complete().map(CompleteRequest::Signal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -551,6 +629,9 @@ impl net_request::CheckedRequest for CheckedRequest {
|
||||
CheckedRequest::HeaderByHash(ref prover, _) =>
|
||||
expect!((&NetResponse::Headers(ref res), &CompleteRequest::Headers(ref req)) =>
|
||||
prover.check_response(cache, &req.start, &res.headers).map(Response::HeaderByHash)),
|
||||
CheckedRequest::HeaderWithAncestors(ref prover, _) =>
|
||||
expect!((&NetResponse::Headers(ref res), &CompleteRequest::Headers(ref req)) =>
|
||||
prover.check_response(cache, &req.start, &res.headers).map(Response::HeaderWithAncestors)),
|
||||
CheckedRequest::TransactionIndex(ref prover, _) =>
|
||||
expect!((&NetResponse::TransactionIndex(ref res), _) =>
|
||||
prover.check_response(cache, res).map(Response::TransactionIndex)),
|
||||
@ -584,6 +665,8 @@ pub enum Response {
|
||||
HeaderProof((H256, U256)),
|
||||
/// Response to a header-by-hash request.
|
||||
HeaderByHash(encoded::Header),
|
||||
/// Response to a header-by-hash with ancestors request.
|
||||
HeaderWithAncestors(Vec<encoded::Header>),
|
||||
/// Response to a transaction-index request.
|
||||
TransactionIndex(net_request::TransactionIndexResponse),
|
||||
/// Response to a receipts request.
|
||||
@ -625,6 +708,10 @@ pub enum Error {
|
||||
Decoder(::rlp::DecoderError),
|
||||
/// Empty response.
|
||||
Empty,
|
||||
/// Response data length exceeds request max.
|
||||
TooManyResults(u64, u64),
|
||||
/// Response data is incomplete.
|
||||
TooFewResults(u64, u64),
|
||||
/// Trie lookup error (result of bad proof)
|
||||
Trie(TrieError),
|
||||
/// Bad inclusion proof
|
||||
@ -641,6 +728,8 @@ pub enum Error {
|
||||
WrongTrieRoot(H256, H256),
|
||||
/// Wrong response kind.
|
||||
WrongKind,
|
||||
/// Wrong sequence of headers.
|
||||
WrongHeaderSequence,
|
||||
}
|
||||
|
||||
impl From<::rlp::DecoderError> for Error {
|
||||
@ -701,6 +790,65 @@ impl HeaderProof {
|
||||
}
|
||||
}
|
||||
|
||||
/// Request for a header by hash with a range of ancestors.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct HeaderWithAncestors {
|
||||
/// Hash of the last block in the range to fetch.
|
||||
pub block_hash: Field<H256>,
|
||||
/// Number of headers before the last block to fetch in addition.
|
||||
pub ancestor_count: u64,
|
||||
}
|
||||
|
||||
impl HeaderWithAncestors {
|
||||
/// Check a response for the headers.
|
||||
pub fn check_response(
|
||||
&self,
|
||||
cache: &Mutex<::cache::Cache>,
|
||||
start: &net_request::HashOrNumber,
|
||||
headers: &[encoded::Header]
|
||||
) -> Result<Vec<encoded::Header>, Error> {
|
||||
let expected_hash = match (self.block_hash, start) {
|
||||
(Field::Scalar(ref h), &net_request::HashOrNumber::Hash(ref h2)) => {
|
||||
if h != h2 { return Err(Error::WrongHash(*h, *h2)) }
|
||||
*h
|
||||
}
|
||||
(_, &net_request::HashOrNumber::Hash(h2)) => h2,
|
||||
_ => return Err(Error::HeaderByNumber),
|
||||
};
|
||||
|
||||
let start_header = headers.first().ok_or(Error::Empty)?;
|
||||
let start_hash = start_header.hash();
|
||||
if start_hash != expected_hash {
|
||||
return Err(Error::WrongHash(expected_hash, start_hash));
|
||||
}
|
||||
|
||||
let expected_len = 1 + cmp::min(self.ancestor_count, start_header.number());
|
||||
let actual_len = headers.len() as u64;
|
||||
match actual_len.cmp(&expected_len) {
|
||||
cmp::Ordering::Less =>
|
||||
return Err(Error::TooFewResults(expected_len, actual_len)),
|
||||
cmp::Ordering::Greater =>
|
||||
return Err(Error::TooManyResults(expected_len, actual_len)),
|
||||
cmp::Ordering::Equal => (),
|
||||
};
|
||||
|
||||
for (header, prev_header) in headers.iter().zip(headers[1..].iter()) {
|
||||
if header.number() != prev_header.number() + 1 ||
|
||||
header.parent_hash() != prev_header.hash()
|
||||
{
|
||||
return Err(Error::WrongHeaderSequence)
|
||||
}
|
||||
}
|
||||
|
||||
let mut cache = cache.lock();
|
||||
for header in headers {
|
||||
cache.insert_block_header(header.hash(), header.clone());
|
||||
}
|
||||
|
||||
Ok(headers.to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
/// Request for a header by hash.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct HeaderByHash(pub Field<H256>);
|
||||
@ -993,6 +1141,83 @@ mod tests {
|
||||
assert!(HeaderByHash(hash.into()).check_response(&cache, &hash.into(), &[raw_header]).is_ok())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_header_with_ancestors() {
|
||||
let mut last_header_hash = H256::default();
|
||||
let mut headers = (0..11).map(|num| {
|
||||
let mut header = Header::new();
|
||||
header.set_number(num);
|
||||
header.set_parent_hash(last_header_hash);
|
||||
|
||||
last_header_hash = header.hash();
|
||||
header
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
headers.reverse(); // because responses are in reverse order
|
||||
|
||||
let raw_headers = headers.iter()
|
||||
.map(|hdr| encoded::Header::new(::rlp::encode(hdr).into_vec()))
|
||||
.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 cache = Mutex::new(make_cache());
|
||||
|
||||
let header_with_ancestors = |hash, count| {
|
||||
HeaderWithAncestors {
|
||||
block_hash: hash,
|
||||
ancestor_count: count
|
||||
}
|
||||
};
|
||||
|
||||
// Correct responses
|
||||
assert!(header_with_ancestors(headers[0].hash().into(), 0)
|
||||
.check_response(&cache, &headers[0].hash().into(), &raw_headers[0..1]).is_ok());
|
||||
assert!(header_with_ancestors(headers[0].hash().into(), 2)
|
||||
.check_response(&cache, &headers[0].hash().into(), &raw_headers[0..3]).is_ok());
|
||||
assert!(header_with_ancestors(headers[0].hash().into(), 10)
|
||||
.check_response(&cache, &headers[0].hash().into(), &raw_headers[0..11]).is_ok());
|
||||
assert!(header_with_ancestors(headers[2].hash().into(), 2)
|
||||
.check_response(&cache, &headers[2].hash().into(), &raw_headers[2..5]).is_ok());
|
||||
assert!(header_with_ancestors(headers[2].hash().into(), 10)
|
||||
.check_response(&cache, &headers[2].hash().into(), &raw_headers[2..11]).is_ok());
|
||||
assert!(header_with_ancestors(invalid_successor.hash().into(), 0)
|
||||
.check_response(&cache, &invalid_successor.hash().into(), &[raw_invalid_successor.clone()]).is_ok());
|
||||
|
||||
// Incorrect responses
|
||||
assert_eq!(header_with_ancestors(invalid_successor.hash().into(), 0)
|
||||
.check_response(&cache, &headers[0].hash().into(), &raw_headers[0..1]),
|
||||
Err(Error::WrongHash(invalid_successor.hash(), headers[0].hash())));
|
||||
assert_eq!(header_with_ancestors(headers[0].hash().into(), 0)
|
||||
.check_response(&cache, &headers[0].hash().into(), &[]),
|
||||
Err(Error::Empty));
|
||||
assert_eq!(header_with_ancestors(headers[0].hash().into(), 10)
|
||||
.check_response(&cache, &headers[0].hash().into(), &raw_headers[0..10]),
|
||||
Err(Error::TooFewResults(11, 10)));
|
||||
assert_eq!(header_with_ancestors(headers[0].hash().into(), 9)
|
||||
.check_response(&cache, &headers[0].hash().into(), &raw_headers[0..11]),
|
||||
Err(Error::TooManyResults(10, 11)));
|
||||
|
||||
let response = &[raw_headers[0].clone(), raw_headers[2].clone()];
|
||||
assert_eq!(header_with_ancestors(headers[0].hash().into(), 1)
|
||||
.check_response(&cache, &headers[0].hash().into(), response),
|
||||
Err(Error::WrongHeaderSequence));
|
||||
|
||||
let response = &[raw_invalid_successor.clone(), raw_headers[0].clone()];
|
||||
assert_eq!(header_with_ancestors(invalid_successor.hash().into(), 1)
|
||||
.check_response(&cache, &invalid_successor.hash().into(), response),
|
||||
Err(Error::WrongHeaderSequence));
|
||||
|
||||
let response = &[raw_invalid_successor.clone(), raw_headers[1].clone()];
|
||||
assert_eq!(header_with_ancestors(invalid_successor.hash().into(), 1)
|
||||
.check_response(&cache, &invalid_successor.hash().into(), response),
|
||||
Err(Error::WrongHeaderSequence));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_body() {
|
||||
use rlp::RlpStream;
|
||||
|
@ -33,6 +33,9 @@ use transaction_queue::TransactionQueue;
|
||||
|
||||
use request;
|
||||
|
||||
/// Maximum allowed size of a headers request.
|
||||
pub const MAX_HEADERS_PER_REQUEST: u64 = 512;
|
||||
|
||||
/// Defines the operations that a provider for the light subprotocol must fulfill.
|
||||
pub trait Provider: Send + Sync {
|
||||
/// Provide current blockchain info.
|
||||
@ -54,7 +57,6 @@ pub trait Provider: Send + Sync {
|
||||
/// results within must adhere to the `skip` and `reverse` parameters.
|
||||
fn block_headers(&self, req: request::CompleteHeadersRequest) -> Option<request::HeadersResponse> {
|
||||
use request::HashOrNumber;
|
||||
const MAX_HEADERS_TO_SEND: u64 = 512;
|
||||
|
||||
if req.max == 0 { return None }
|
||||
|
||||
@ -83,7 +85,7 @@ pub trait Provider: Send + Sync {
|
||||
}
|
||||
};
|
||||
|
||||
let max = ::std::cmp::min(MAX_HEADERS_TO_SEND, req.max);
|
||||
let max = ::std::cmp::min(MAX_HEADERS_PER_REQUEST, req.max);
|
||||
|
||||
let headers: Vec<_> = (0u64..max)
|
||||
.map(|x: u64| x.saturating_mul(req.skip.saturating_add(1)))
|
||||
@ -128,7 +130,7 @@ pub trait Provider: Send + Sync {
|
||||
fn header_proof(&self, req: request::CompleteHeaderProofRequest) -> Option<request::HeaderProofResponse>;
|
||||
|
||||
/// Provide pending transactions.
|
||||
fn ready_transactions(&self, max_len: usize) -> Vec<PendingTransaction>;
|
||||
fn transactions_to_propagate(&self) -> Vec<PendingTransaction>;
|
||||
|
||||
/// Provide a proof-of-execution for the given transaction proof request.
|
||||
/// Returns a vector of all state items necessary to execute the transaction.
|
||||
@ -283,8 +285,8 @@ impl<T: ProvingBlockChainClient + ?Sized> Provider for T {
|
||||
.map(|(_, proof)| ::request::ExecutionResponse { items: proof })
|
||||
}
|
||||
|
||||
fn ready_transactions(&self, max_len: usize) -> Vec<PendingTransaction> {
|
||||
BlockChainClient::ready_transactions(self, max_len)
|
||||
fn transactions_to_propagate(&self) -> Vec<PendingTransaction> {
|
||||
BlockChainClient::transactions_to_propagate(self)
|
||||
.into_iter()
|
||||
.map(|tx| tx.pending().clone())
|
||||
.collect()
|
||||
@ -370,12 +372,10 @@ impl<L: AsLightClient + Send + Sync> Provider for LightProvider<L> {
|
||||
None
|
||||
}
|
||||
|
||||
fn ready_transactions(&self, max_len: usize) -> Vec<PendingTransaction> {
|
||||
fn transactions_to_propagate(&self) -> Vec<PendingTransaction> {
|
||||
let chain_info = self.chain_info();
|
||||
let mut transactions = self.txqueue.read()
|
||||
.ready_transactions(chain_info.best_block_number, chain_info.best_block_timestamp);
|
||||
transactions.truncate(max_len);
|
||||
transactions
|
||||
self.txqueue.read()
|
||||
.ready_transactions(chain_info.best_block_number, chain_info.best_block_timestamp)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,10 +6,10 @@
|
||||
"minimumDifficulty": "0x020000",
|
||||
"difficultyBoundDivisor": "0x0800",
|
||||
"durationLimit": "0x0d",
|
||||
"blockReward": "0x4563918244F40000",
|
||||
"blockReward": "0x29A2241AF62C0000",
|
||||
"homesteadTransition": "0x0",
|
||||
"eip649Reward": "0x29A2241AF62C0000",
|
||||
"eip100bTransition": "0x0",
|
||||
"eip649Reward": "0x29A2241AF62C0000",
|
||||
"eip649Transition": "0x0"
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,16 +1,18 @@
|
||||
{
|
||||
"name": "Byzantium (Test)",
|
||||
"name": "Constantinople (test)",
|
||||
"engine": {
|
||||
"Ethash": {
|
||||
"params": {
|
||||
"minimumDifficulty": "0x020000",
|
||||
"difficultyBoundDivisor": "0x0800",
|
||||
"durationLimit": "0x0d",
|
||||
"blockReward": "0x4563918244F40000",
|
||||
"blockReward": "0x29A2241AF62C0000",
|
||||
"homesteadTransition": "0x0",
|
||||
"eip649Reward": "0x29A2241AF62C0000",
|
||||
"eip100bTransition": "0x0",
|
||||
"eip649Transition": "0x0"
|
||||
"eip649Transition": "0x5",
|
||||
"eip649Reward": "0x1BC16D674EC80000",
|
||||
"eip1234Transition": "0x5",
|
||||
"eip1234Reward": "0x1BC16D674EC80000"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -29,11 +31,14 @@
|
||||
"eip161abcTransition": "0x0",
|
||||
"eip161dTransition": "0x0",
|
||||
"eip140Transition": "0x0",
|
||||
"eip210Transition": "0x0",
|
||||
"eip211Transition": "0x0",
|
||||
"eip214Transition": "0x0",
|
||||
"eip155Transition": "0x0",
|
||||
"eip658Transition": "0x0"
|
||||
"eip658Transition": "0x0",
|
||||
"eip145Transition": "0x0",
|
||||
"eip1014Transition": "0x0",
|
||||
"eip1052Transition": "0x0",
|
||||
"eip1283Transition": "0x0"
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
@ -54,9 +59,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 } } } }
|
||||
}
|
||||
}
|
||||
|
@ -27,8 +27,7 @@
|
||||
"eip155Transition": "0x0",
|
||||
"eip161abcTransition": "0x7fffffffffffffff",
|
||||
"eip161dTransition": "0x7fffffffffffffff",
|
||||
"eip98Transition": "0x7fffffffffffff",
|
||||
"eip86Transition": "0x7fffffffffffff"
|
||||
"eip98Transition": "0x7fffffffffffff"
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
|
@ -23,7 +23,6 @@
|
||||
"eip161abcTransition": "0x7fffffffffffffff",
|
||||
"eip161dTransition": "0x7fffffffffffffff",
|
||||
"eip98Transition": "0x7fffffffffffffff",
|
||||
"eip86Transition": "0x7fffffffffffffff",
|
||||
"eip155Transition": "0x7fffffffffffffff",
|
||||
"maxCodeSize": 24576,
|
||||
"maxCodeSizeTransition": "0x7fffffffffffffff"
|
||||
|
@ -23,8 +23,7 @@
|
||||
"eip161abcTransition": "0x0",
|
||||
"eip161dTransition": "0x0",
|
||||
"eip98Transition": "0x7fffffffffffffff",
|
||||
"eip86Transition": "0x7fffffffffffffff",
|
||||
"eip155Transition": "0x7fffffffffffffff",
|
||||
"eip155Transition": "0x0",
|
||||
"maxCodeSize": 24576,
|
||||
"maxCodeSizeTransition": "0x0"
|
||||
},
|
||||
|
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 } } } }
|
||||
}
|
||||
}
|
@ -29,7 +29,6 @@
|
||||
"eip161dTransition": "0x7fffffffffffffff",
|
||||
"eip155Transition": "0x0",
|
||||
"eip98Transition": "0x7fffffffffffff",
|
||||
"eip86Transition": "0x7fffffffffffff",
|
||||
"wasmActivationTransition": 2000000,
|
||||
"eip140Transition": 2000000,
|
||||
"eip211Transition": 2000000,
|
||||
|
@ -38,7 +38,6 @@
|
||||
"eip161abcTransition": "0x927C0",
|
||||
"eip161dTransition": "0x927C0",
|
||||
"eip98Transition": "0x7fffffffffffff",
|
||||
"eip86Transition": "0x7fffffffffffff",
|
||||
"eip155Transition": "0x927C0",
|
||||
"eip140Transition": "0xC3500",
|
||||
"eip211Transition": "0xC3500",
|
||||
|
@ -150,7 +150,6 @@
|
||||
"eip161dTransition": 2675000,
|
||||
"eip155Transition": 2675000,
|
||||
"eip98Transition": "0x7fffffffffffff",
|
||||
"eip86Transition": "0x7fffffffffffff",
|
||||
"maxCodeSize": 24576,
|
||||
"maxCodeSizeTransition": 2675000,
|
||||
"eip140Transition": 4370000,
|
||||
@ -173,9 +172,9 @@
|
||||
"gasLimit": "0x1388",
|
||||
"stateRoot": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544"
|
||||
},
|
||||
"hardcodedSync": {
|
||||
"header": "f90207a0cdaf426b80edd4363b336b351cbfec8c38b44847cdbd814aa92e92bc9ec05333a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347949435d50503aee35c8757ae4933f7a0ab56597805a03f28b2b384dbfd29bc0a10343e8a419e61b92782f880046170bf1d11455e94bba0f3712ef3ff24efe1afc7da11ffb2ca495a94fe7958f42e9f1599d66ed72af13ba06d01d03a15f807da601bd2dfde7490bbe91d9bb11c11eda435db9daad6e7b1efb9010000008c0000c000000000440100108040000082000800000000000000040801001004001000000010000000001000043300001000008000800000002000200040000000580c0004108000040c0008000006000000000280800080000800000000402000000a000000a810226200002881004000208006020000000510030000100040010100000086c20000000009000100000190008c80060000008000202080420008056040000000001000400001100010140822800220000c804004002000108000160001400200088082008000000412100010080205011000000800a0000810021005000000000002840000000400000000880000006000000000200002870bfca554dbc6398358b001837a137083473c8e845b27f4fd86436f72746578a0dbf31fd28bd8f69f1103196e1782a9dfb636bcfa726362ab0767235cb8d56e7188264402501145497f",
|
||||
"totalDifficulty": "4838383800145139949936",
|
||||
"hardcodedSync": {
|
||||
"header": "f90206a0391c42ff4f047145a6b9a14179c3cc404b31d92f30693e28cf2bba41f47f6329a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794b2930b35844a230f00e51431acae96fe543a0347a0fb280d4457e60a0b96577e1dde9e00905102cfd36def5c5b31dcc2284636136ea077f739c324e35c7448b14aa02186973d3c74cc1ab081498cd0c487a604873723a0e462d76b5204d14b13d1f1b39ea048a3b637f91d42c729c367d5bbdbd0a72d70b90100008003410402005000200009400030c40490500208480008414000a40048806408000080802008204400010001800c0020080c0a00400105a9080820400900240000084012030a1504030508000200005c4404a0c3490820000010400811040004708a1006910211444040c28001a800e920d00000940c200119111a10401001008044214002002080c21081801e008a320848a204400042400898004004010028840181106210080254a081112480031000410202440092c880be3894000120050500860880000108000c0080009e0000204007212840808cb80200601024020000210280100c018540b28a1041a62400000108204084000008808040000004870bc009a1914d7f8362f801837a121d8379ee5a845bbd53ca8573696e6731a0abce0f90ce69f740080eeb94d1cb13981fafe3bc6d020a44815acd86cbd3fc0a889501b04c0614e053",
|
||||
"totalDifficulty": "7128515864594819065361",
|
||||
"CHTs": [
|
||||
"0x0eb474b7721727204978e92e27d31cddff56471911e424a4c8271c35f9c982cc",
|
||||
"0xe10e94515fb5ffb7ffa9bf50db4a959b3f50c2ff75e0b8bd5f5e038749e52a11",
|
||||
@ -3014,7 +3013,336 @@
|
||||
"0x118b3ae7ad25ab96fe8a63973312c758d4ce9ecd39cc24913c26a65b4b5534de",
|
||||
"0x19cd088af8dbe2d3e6ca7987d9ee1564ea2256f482840b1d2f0da85060de9a86",
|
||||
"0x98bc07422cf8b0c4d1428afb759300d9a7637de2518528d34f7d237be7e863be",
|
||||
"0x0c64526b393066911c7da3f17f9e652cfa38112ae324e3c84416e811d3fe7cad"
|
||||
"0x0c64526b393066911c7da3f17f9e652cfa38112ae324e3c84416e811d3fe7cad",
|
||||
"0xa30cbfaf518996ba776b426a7068faad4ee49775db45565ebd327f9c679a45b4",
|
||||
"0xd3e1a807f5940ee1a321b20b7931bef90515132ea9959df94e55529e05802cab",
|
||||
"0x338aef579d9ec8acc1a0411c1674bcf213d03aa7d4bbc56707e081829ce30004",
|
||||
"0x68c7a603089a220273f019001a39bfa9194590a6fa6d8ba960ddf4888b105a6b",
|
||||
"0xd6a9d2c354e1dd77322800d24774eb03b589dd94bcdb3cc2b70437ed70411e6a",
|
||||
"0x39c017c42ad571564792bf5741b3ae786ff0c24ebcb5ee46882ce0545b8a2262",
|
||||
"0xf5caea6b23f4085c9f94c880d89b1c23eb69c03dc098b426143ae4b28969a2d8",
|
||||
"0x959eebc05ff0dfae8c7e6699f069b38b5f2e5bc8c155bc35fc7f578d2d112993",
|
||||
"0x199e90557d4d9e13c3e7a4b5b4ef6fe52cd2c724c36eaa44b7fa151efebbbeee",
|
||||
"0x0bfe35d253227696e76f92ff13e4c545c57fca51186a16f687e76d2e6707d34f",
|
||||
"0xadf8b7678f98b0e5009130d9d5d77add6e460b67b0529abc5315c44dadea0cb4",
|
||||
"0x86582f3a98b218939aefd7eea438ee278d1faaf41920e8c72922c46fd56f1c32",
|
||||
"0x001b728a4737fdd53cde20341fa0adec9aa8ab7c7c1db244fbd509a6c4f3f364",
|
||||
"0x9207900bfdd6c87e2ba8498c0372706799604a207930eeb331580459d17f89cb",
|
||||
"0xd2192fcf74cad70e6f7986a0b088de8658a14638a4c03d7ae616a88ceea00ba2",
|
||||
"0xbf6f6b91742eebe70204eb7a70196ef636fc2db4d4c4f89cd5826fbf990a945d",
|
||||
"0x5c1210951949402fe3b012577f1af0d3e285a0b39c3fe19c84f7930e003c06de",
|
||||
"0xa16d57f777f94f032f7f2f75b2e25ebd11559effee98b39a5a1e7cc804cfbf06",
|
||||
"0x1b9561fb8035ec6955454d6710f053d7ad3d8e0753aaac568ac3bc98f874465e",
|
||||
"0x1a622da786425e0b65b9083a451a419c75e16908fa04d89ddc2c11d94ffe65a0",
|
||||
"0xbfcb9b1d847eb40b6808e45bf3d2fb8f6588d6f103167be65f246d0733afd1f7",
|
||||
"0x2317640589ab9d52e7f5e8dda95ff3b1beceacc5832341e9053b71209bfad07f",
|
||||
"0xa10611b829dbb533e565ad01632b26b1fd642a4393e7fdd9b8f235f11bb606c8",
|
||||
"0xe4ea4173982f342e396356b0bb0eb47e6748461ecce0f34dbe8fc084cf6a9fbc",
|
||||
"0xd58399c0d0ae878338d2915eaf2d65f2d1e29eb8d551d254e68bce7a8235adcb",
|
||||
"0xc0c8b73ffc675a207f73903c49d81131e6831e4c8e071b988ed9f2a5d2277024",
|
||||
"0xe1ca77bafa66bb055c671978b3d1bd5df32f8e269330507f071afd627012b6af",
|
||||
"0x67a1093cbddf41264009d1dbbc33fbc25a337339be0727e70c512b585897749c",
|
||||
"0x0fd615782db5cf4c0a3686721cbc6245696c1bc9b403a9eaffae00968d2c8ece",
|
||||
"0xc3c2dcaee8954ca86d9b3e4e98c4bb4f6b6bc183f9eb062016c5a25b2280717b",
|
||||
"0x70265915f5ed94d589afafa3d0d0eab6310195cc690aa82bd65e4a488b398c58",
|
||||
"0xde3fead8ce29c04a86dcb081da2cabda5366d28de5ebfe2f8064780413f71edf",
|
||||
"0x0ae43394fcf6ebdabdcc1ede314fe779eb61a12eab807a9d3437d9167e2247e3",
|
||||
"0x3241127e2c7fbb3db9fe0c602b0c94e22c684b7910ffcf09c1c443e567f95e4d",
|
||||
"0xcb94ba286eeaa1129b490bb5891e603fd35e85c97c2132c1216d1774f9017f35",
|
||||
"0xbf396cd23c29ef21fb535880ef621457fb71981f856f2a09c494cd005d38f981",
|
||||
"0x3df0c90ed7aba260e820ca1d28ce1778149e163524e306309aa346bbadedcf2b",
|
||||
"0x66a2724f7481aa3ab83a8f1bae2caef8a7bc607c7ffd5bbb1cf3766741db804f",
|
||||
"0x7a0c3492f4022322e10d81bc10a5db9aceec81d1ab70cdffd31418b79d750fd2",
|
||||
"0x96a826cb667924ed75ec708bf07cf4c7c05f84a0132e154b71eaf6e193590e87",
|
||||
"0xcc7030fe617c318a31984d04e3d7f2ff2196894bc429f3f64bfd69b969dc9b56",
|
||||
"0x3fa94aae223f5aeb593246f1a93d6d694b48946c09d879e791f1188a9dedc4c0",
|
||||
"0xd49e51fc324fe58159575c0c24171f4eb1aaf58ed8e1311c3849538c8cec3ce1",
|
||||
"0xc474123906eae5cd48a10e0d93fcbbd653f0c6d25275f827d4fac51e696c3d91",
|
||||
"0xacd7b790a19026fa3f3b0a354878d4fcd79dc600f7ba5cedd2eefffe1ceda76c",
|
||||
"0x41b311a188cd7ce1444d258dc379994b81a895226276c7bfe5e6cb29a5f92142",
|
||||
"0xda0ae01db7f73f07fce46b94c24d6e400598378a6baf01123dd710c5425fb8c9",
|
||||
"0xe62e08175a02b575e28b9e029a838c365e3ce4278f60c2d3b5d529768a4b47c4",
|
||||
"0x99b804c8d0feda7f9df961527d634fb8b2d477a362e1d8158856885a13425fa9",
|
||||
"0xe73597be8ef7d78f862c7a94a8ccff17f559816eba2f830821c6f6436898f9fb",
|
||||
"0x36de9ee4c80853c865b16904cd8f6c0e9a99ff9e7bf05100bfbc76789cedd4d1",
|
||||
"0xf480b762872373102393461ff3a21323a1df799c315fd167780a45d7bfaae84e",
|
||||
"0x303b66babd21e72449cad413e04bdb0bc3ebcbb84a79dd30ed7c972c5341b82b",
|
||||
"0xbf111684fbe44a973594f31cdee2c94e807bff9cf7584c22dcd609d8234f6e62",
|
||||
"0x79b26cc3bbf49b6f25afbff7e97e4e45f2dcb359095fdbeb7fb7addee692afc3",
|
||||
"0x2839d620cc140ba838ecba6e7e52db8cf7b5cd4cf4857f72f3bfbc9b1cf0fbd9",
|
||||
"0x93074136f4eec367adcf27955d38efc0dc6da514693bfc97935c7871793e35ea",
|
||||
"0x21f5af18a4cf0096b6e6a3d4c98f4043cfee5c4ee085ce106f86b713160144b8",
|
||||
"0x90d16b403e2deca6cd5c80e52eba0b84b2875e1dfd75fffb1a2f82bc91eb6942",
|
||||
"0x8a5cb6854c19a865f51e3ee9eaf8e843a97b272f6467634ba40e547a435ef624",
|
||||
"0x9afe42a0dffca8ec063c83908fd6237d6130c9dfeab57078bdd02b6ac6d0ea07",
|
||||
"0xa05cc6108b475d3e68e280e98f514cfb6df4f004e1b7708fcfd4528d346bea6b",
|
||||
"0x71f10879b875caefab46669e8525b9c0487bbe3247e43a6cdb1dedbfb4d4ba33",
|
||||
"0x7debdafd2b1410469fd76e2a39dcd1b8f400292f5359ecd39186a5be0f9e44b8",
|
||||
"0x076f8741b668f3f715a7142f5c1592ffb58ca13e8612edc340619a1ca6ce3f2a",
|
||||
"0xe312bb85cd945eb45f72868e6651633964f22ce3ffcbd0f3701bf57ac0c13edd",
|
||||
"0xe6eae7aad7fed9c690a14eb7aa107c83a5e54736940ac6d82e251181e1103eae",
|
||||
"0x794c8ade9063600442f83d4be14d7bbb191c692314253a2c62dcb33f3e7d28bd",
|
||||
"0x6fd9db41dc1074a4349a6d3881757ad931bdf9ec261fc4e0a5ba9cfa5fafbf41",
|
||||
"0x37557ead7100564651992a919949af3f39f3eacc03aa0ea158dd59abc4e2a93d",
|
||||
"0x7a3b01cf210dfc42e4e41c95af1af357d15409fecae888abf4fa35149f44ed2e",
|
||||
"0x89e952ed9afda8aa0ff80ceb90e5857dc7fc3cb6259ac6089da5fed49223cf42",
|
||||
"0xf1ae8d3769142a1f3c8bc0ecf8454f05b09354a2ad5c921d0a6845417bc2f244",
|
||||
"0xa04e022b2afd83a1e14d0d67595070b29f196dcfc05d92b2ce7c582d67af4a00",
|
||||
"0xa3a0c85dfc3d8055a29de34492b3e231691bb6e9ca06684a205837ab9870c72e",
|
||||
"0xee2529ad0af60748cc0bd8d97189d878643a52710dd200f79f27d8a4a4c8c093",
|
||||
"0xac88fe07805a058f1341ed89795f0e5e9ace050de0742f863c1c9c63b17aed12",
|
||||
"0x8fddc716ab43397541f6b22644949c6d7214b01ca8223310a34840df37c47746",
|
||||
"0x3cbb4d1a2ea6fce170de64b1f4bbb8d9239fe191018b737e62eda77aeb7d0306",
|
||||
"0x3807421ad84d6f2f9d5d830364a0455d6846e114b87cd08a3cb9a33e40c7c084",
|
||||
"0x283199cbf0e1c997025bd36522619417d9e6184073b830fb22c3de106a68b598",
|
||||
"0xcbc85a7ee2122abad27b1f5a07bd15d864af382a62fd552092b7feec4d2e4856",
|
||||
"0x84586eae7108f2e1217d53be81f26bff7cc35409c64c1af827bb5263d813302f",
|
||||
"0x5d2d93535aa7db5e2204e419ecf4d7c0647ce40522806bd24ecf348eb49a1f17",
|
||||
"0x3a6118c84312f120c0d3e4ae4ec0b8103448da31953fa27a8400ed7e4875897e",
|
||||
"0x4a0d1639274d31dc5d9eb49338b204e9cc9610913c0320e7da74a02ed2486fb6",
|
||||
"0xa7770b7cf4f83c387344cff6ddd3441dd131333df0f210a57a271fc1a61f08f8",
|
||||
"0x35066ce607eafc9bdd3386097a98c844bda683ce29faf25708b1a2f3e25c9aca",
|
||||
"0x7068b1f5c017ff5b995f2c65db7daed3cd9fd0e658322ee2debbba7de3ebdd72",
|
||||
"0xfbcf8cec0ed675d12ab4fab45754fd00a329d19ad77afe4413a0581bb6dab8dd",
|
||||
"0x78035e412813b0a3f7e3f46bafe436b57b83278499fe8b8a1bdb3066f538d0b1",
|
||||
"0x28bfbcd7eb38793a1ea711b6dd73c55da0faee3a9707c743737f0692dc6b56a1",
|
||||
"0x9fb1607599329b61570a0daeb7b1a93210ac286e02a64ae309e1950cdd76c5e5",
|
||||
"0x8903d98196291218a50fe03a5cd51592e1b458315491d735187cb39d0e21f397",
|
||||
"0x97aa20d84821d36a44ce18eff501df95549c8266220ad612d0ba9d293d65271a",
|
||||
"0x3245e35a2c6d46002dbf5bfedee31fd28a88409edbc55ee1ef7972a249b1cce2",
|
||||
"0xd6149428168dbf78ab2f706f041a61e3074e3d18ed47bd343d54c3e4f2e051fe",
|
||||
"0x9f4a04d0e3a2b8773a258bfcdee5242e44761aa1a1d2f9a7162f04a2b85de6c8",
|
||||
"0x0162a3449c2be2a0a45a771027e5fb67169c5a56c4ef6f386093fa79f9942fce",
|
||||
"0x5c1196a72f2c6fb5771e0390ef25499acd52c6aeeac3615ff17dcf2c405069ca",
|
||||
"0x319097551b7df30bc67f5ee6f068cf3b34e71371b91635e9009af7acfe97e12d",
|
||||
"0x8b89e2e091824d0c3276128543991cf7c35a82bed4b92b4e67aeb4652033a823",
|
||||
"0x75d6dd431d5568625946b3578e68d47523518cb2e141369aee5273fb7cdc4013",
|
||||
"0xc473b7b23c164759487af8c96865f0f3af3f3e40e9607665f94f937c3334f604",
|
||||
"0x1f61783925fc03f3f5465f37aad2276c466ddb91a47db036f042c0b2edbbf643",
|
||||
"0x3f6370976528cc31e4d099711329d5c670a2538623621b164d470fd7ee2cfb17",
|
||||
"0x3705bd7548fcdeb0dbb3162394edb2adcd5128524eb837b71a04ff0c9c21c22b",
|
||||
"0xe15e99e427efae16230af47e59ff89b76df25db44fa2dfe95d2419b6de35ee7a",
|
||||
"0xbb4a17b5e4879b52e6a4838df9525ae01b168197db2910caea805011588559a7",
|
||||
"0x60e6cc67da461bafef5c3b7e4f9e964a24c3146c4fc22c2e046301e457d1cdfc",
|
||||
"0x72ef37234da6fe157e0e87b11528c3e41d115f10f1dcfce60e54d83c1406989a",
|
||||
"0x63c3a73812427f73be785d4690a6ff81912d3ac17c8d76970ded284383ec97a2",
|
||||
"0xf88c0457e00ec47c27ddc6d99fe6c0b82bf9249018a96b1c7e6b90e906adfaad",
|
||||
"0x9258fa102e450844e091b58dfff2fd05b8fa099d53667626e340fda7ff7f9bd1",
|
||||
"0x68adeaa1063528386db31407596442f815769731da8b560272ba3e1b8817a11a",
|
||||
"0x222a41b6e681d2acf8a9fbd9310d34145a3c49160c29681b95c85176abadddf2",
|
||||
"0x00745c4bb8cf5fb63700444f9258eb94e4b527ba8739fed4bbd7b13083854929",
|
||||
"0xf27199044245d103b296bb81188982baa87175843b06424e0b5fe9dc6e005705",
|
||||
"0xe00c3bfee8d71930faae9ca720f25f342ad166f438c07b0664c0c2d6b9f82c58",
|
||||
"0x05e2bd6caee8a926c0f61bd0e5553b304656cf4749f54bb45b72d2a84fcf2378",
|
||||
"0xcff8627a22e37d1087c3b858079a4f90a1fac65cd397dce26be8c3efe2515e1e",
|
||||
"0x4885a5f8fb2e367a9edb32b02ad4390a4ef8f317a0e7d3bcfd5eccb9d8d05b1d",
|
||||
"0x194638cb01699bfdb67b09ce5e2e8d5dbcfd403ae325a7a0311923ba5207c5b6",
|
||||
"0x20e7c0ec1db7ca6adeeeb0c7950b7911e1627bb173425c4eaa105cfcc9c43db6",
|
||||
"0x1010eb2f28d04da879c67f4c9e51fd480753081eac6123c5161502f3180764f0",
|
||||
"0x09a0d0aac41a4e2fadb48c1751011fb46774f10ee263567d823e275aa0a33ec3",
|
||||
"0xde190e4dde46d967a4e32ecfda15323c7f4081f40d5f245916055af44b008e81",
|
||||
"0x21870402899f8c05003a175f2c0d37fdfb52c9bda3eea3ac8616c832fd8ac173",
|
||||
"0xbec735492b66890aeb0ccb5611a84a908477269c2336e076c42cbb620cee8861",
|
||||
"0xb9daeedd739766f82a95505a9e71daa503a5f0c3ee1a6a97f842b2ffb6ddc6ad",
|
||||
"0x9f30d706fc86c7322a10a3c572df2ef4f2f49bcb49c5afc2c6299cf051e2e38f",
|
||||
"0x9dc1d641fab155885db408328e60c06d97a0e3327b64a18d46e7ced7cacff446",
|
||||
"0x252594a4da3cc4e794d954e88c15a2c847dd84d895eca06b9365a85a71fc46eb",
|
||||
"0x979ea7682319cb0674066b10eb7919a87ad1ec0618ddb24723f13c55899cbb6c",
|
||||
"0x570b4dce3b4613a8266688291f06bafa9d3b7828e3e6a9bfd27e7d2f3ba59125",
|
||||
"0x39e97e3c20af2dcfa347ec193cae2c00100effd4f3987bfe21973db8c5e11fc5",
|
||||
"0xf66b0859b41bf7dc53dd23762ecc593f4572a8a9f82b4c51257af1eda6344bcf",
|
||||
"0xfc32a5b84537ed5947874eca72d189f74676855be5ded4d32eac2ebc0c3a3306",
|
||||
"0xa89c577f12bedcc225cdfbf86ebe8112aef97b9c34a504dda52cea4f40f72be1",
|
||||
"0x67e4b71c08fd93f1c37cc60826c5d8c18e14b89a7f271e0828b114de39aff694",
|
||||
"0x342279789cd6a721f5f4866e3a16d19f88b24ac277563ec7b0716ecdf8dace3d",
|
||||
"0x220a5babb290dc16440f4b01bc117c41af5073110b1375cae0317f9fd364d44c",
|
||||
"0xbc1019eec10ff493e095915f66d46f0855b55aa681352774dc300d54147efb00",
|
||||
"0xa9cc80ffc08c2b4c38fa178e3ac56ef982d0487b7139ed241fdda3894f4b67e2",
|
||||
"0xb35267a4b6020a2e53e112f4ba7807ec50ba78a3b2d64fc3e3bfe918bb25bd9e",
|
||||
"0xd5021c0c199dbb1b61e5e0d4bcd59fd064ddb6d6611421e57161f9c37fba91f0",
|
||||
"0xea0af5bbcc015b06951c9ff3df3c233f4bdd6ef8eab97f0b3a9e10b01efd7a5a",
|
||||
"0xc060f20f45851e6de2fe1dcb6d8996add5335c34892f84a1db711d0c47c5da4a",
|
||||
"0xbd30199b078305b459565598fea6740a4d187e4813d3887f72d7958ebcc8da48",
|
||||
"0xeafa07e96737a0e53ee7a09bc1b394ae4c1ec6c937901a8066b0cb6b6908aff5",
|
||||
"0x68abed404e0a66ded23d152fc5544b14b0a4fe918a51b667f2dc827575c12136",
|
||||
"0x27da4b5111565097dba6e6dade4f0275ea8234b50f391aa270bb3cfb361e6331",
|
||||
"0x85126b95e3532b5045710f60d0aa3f6b0e801130722bc7d85a67479e0b1fba25",
|
||||
"0x658afe5a3d3b0916372785f952d92069045b747fc67be6c8bce3d695a434d058",
|
||||
"0x9017ad7725867d37402da5ef1727289abcdf9982a0c7dbd7fa6f175ef8ff5f90",
|
||||
"0x892a34192371a1de6d4c2ceabeff5aa9e26c3f41e74260d305872f366bdb73d1",
|
||||
"0x786a848c13f84c87ca554654f0ab35f7fea5014669d919595e087e6463c47253",
|
||||
"0xf1235641dd0ac33ed19e39ee58e282f2e0dd8edc0949e0510f2c65469d85e1ef",
|
||||
"0xa55273939373f7a4052d8bc36501fe17d9b571fd170041ada7b4385d49ecb5e6",
|
||||
"0x79ba81c39c2e7dad9768cdbf754242dc2b5b74fde750c32ee153ab121a633406",
|
||||
"0x74ef128355bdc842c1b109d4b1d3dc6f85a21a110b32fe1b4ce71cd282a20ba5",
|
||||
"0xf0a05137693ab9dae7624cbf4abce1554d4921014cda61584d649c66e9eb09f0",
|
||||
"0x5566a8d7495aae3cb42e66bcc683bb194f53894e3281812484bf36da583b7d9a",
|
||||
"0xbe65f10ed3eb5e862850eb4e30c73172f5417634b087b1dece7df97dda2857c9",
|
||||
"0x5ad40161397a2d0f53d71284d878e711b6d73930d2a79a789e4bf08223e9eeb9",
|
||||
"0x1a88c4e12ba89abf67c8f8de223964e4f3d0ee8951b9a1851c9172b278b956e8",
|
||||
"0xc1bae22721de65936975b20b01380c7707cb603622106a166c1472bdcaaaf94b",
|
||||
"0x68106522840c17b0e93b0cacfdbb1d2c5b219cb90aa61a5d0b04a0291caa4b82",
|
||||
"0x0e8a214b18b92fc025bd374a8d9859244b3855a7d3a364d1a0e092546a17b2b0",
|
||||
"0x584294fe2fc330adfcbbaf251480f2c727da2d38ce54ffcc1b363adb9c0fdb0a",
|
||||
"0xb86b9042acd8d6dd4eaa967b3dce6e4e49cbad95f4a7cfea95299da0cb3aecab",
|
||||
"0x99d4f215dabbe6bcd894d4ce7ee6d16a4543c38d9ab19a4f3b933f37eaa7fa5f",
|
||||
"0xd078bfda23ecf966b656aabf0bb69d27902d33773b2471145268426846a5a1b8",
|
||||
"0x87234af13d71e681c987c38fcc3661889b406e298e3a1ffbd5115fe6fe6e65c8",
|
||||
"0xb9f78fdabc8cd4fbb08fd1e1d00ed552c4bc7cba0672ce91c52deb2834a7b223",
|
||||
"0x76704df0766b51c9327acf08ffd35fb9c3f041b73808094b0d4ae1f7e7d7d0b8",
|
||||
"0xb5e4ec16c993e2ade6e951099512deb2f8fd07956e4d97dfc639a7eeef96d336",
|
||||
"0xc9c919862f5a82a5381e7def2883049fbbb99f24be9902152323811e32db40bc",
|
||||
"0x8df21edd784b8b776ffd603a6da87a6602e6424cb3905d977b909a7b10160abe",
|
||||
"0xd5c524bf24c3c8f2e9cccd5aff20b96fbb8f2045f37ef1014eeea1b82787361f",
|
||||
"0xb64756c799db5e1eca16416cb833605916a9bbbcb3c82a54def34f16e6fcfdaa",
|
||||
"0xfac273bab2facbfc28e2c53c03a44e69ddadfbf57b08499bb43855abae456f1c",
|
||||
"0x43f8990cdc4735bc47fd89cd23c9a99d5453885b1903d4b3185b6b0413735ff6",
|
||||
"0x7420a69d819df5f4106fc9e315e8c125c8876a3a1cae8ef7198a921c121792ec",
|
||||
"0x696861af19fa56f07d5e2eacffa3508cc3638b7acfe4789c002929dfdc47fc3a",
|
||||
"0x86c80d2150fca01803a41a900e66b764ce82af2e0ec19fde53971afbb6390ead",
|
||||
"0x9cf14af73b44b555ceec13119567723ae8e8af927a6f24846635ff5000acfec6",
|
||||
"0x95b50e682e4b6b2a08606a62bce427682ce484c2056d891dc206fae9e062d3f0",
|
||||
"0x789755e975f432a059cb5cbeb067c8f9dfd97b54d8d1a45a1e47592d9eb770d6",
|
||||
"0x87b682b780890ad3d542c76548d7d5287fb244291d62619ed079340293a245d6",
|
||||
"0x8c0155b066048d9e95f5eb1b6ecfcc179feb71ee0426301b03f778573eeee7a7",
|
||||
"0x0fe45f09ef25d05e5c42751a35714af86a5d7a4fa235956edaa36dd0e5ea7533",
|
||||
"0x3b5ee72615fcc04f48cec067ba2d1d9bc0e64c4cdf9d5bcf97c1a999ae940245",
|
||||
"0xcf773973676c9b0e31a549d78a6bbc79826c471b6fed42078d9b35a08d1d28a0",
|
||||
"0xd5ecadc4dba308c0d790adea1e118d6984716600091d341276311631acfbb267",
|
||||
"0xf344c0cf6516f0fa6617e48076726aefbdaaf5a31f67ad8199bc3f6e426bf904",
|
||||
"0x3f3d2d33f36ba9009e9a72f3f5bbcb5df5392a19fc7afc8d37823aaf52b03477",
|
||||
"0x346a89411f090d559ff90e670bf0a385b1b09f117fc9ffa18b09d3b6d5d8e45c",
|
||||
"0x5bc5689e2b4572b8ceea472cc7827e22cbfd018920beebf5c5b25f65f5cd5357",
|
||||
"0xda418efcaa0076f77e4d2f0c57fc32fa67179a5631d9df52d56497113d0e87af",
|
||||
"0x5a8050832e835202695129f6f384652827e61ea5f1be7ff300183201d8bd6b4d",
|
||||
"0xd9f444c382da42c310bd2f05955187163ae7b224e5efd44ab95af332e197d374",
|
||||
"0x9ef2c5bad361117eedbc2adcb72a2ef5eba4caf3a99a0cbb2a65a94d185e48ae",
|
||||
"0x7e3e089bc46b00a4174d90003379c382ab5bd84d092b9c4db3189d2bdc24f00b",
|
||||
"0x94f50fb12eed909d251fe69adb1a1f214776cb029d487360b55c3a2abb663d7e",
|
||||
"0xd3e1f4244dea40d0741255db2dae72103e263390e0ccfdefcbb2da59ecc5ec9f",
|
||||
"0x6808bf0cb7d4b677527de762b6db8ddf74a1b272349f34f44505912bd95d62f3",
|
||||
"0xbf7672ac474b5b849bc086ff8455216f015c8fc7660436dee153522ef6991c04",
|
||||
"0xe79d27a369cdd5455ddbc6bd9158cd1870aa895b3c3971d07f1555b95ed02ac3",
|
||||
"0xfa9e20a36c11b0dfbf7e9c62872a6423f5460dfd18e447481461a41176678262",
|
||||
"0xaafb6c407910341bedc82c0f260cdef75ce5653f644b93a465cb990247a32986",
|
||||
"0x5058e655e0c179e6c20f48fbd08c2f34f9341f6c07972ff40f55bfabbc783b12",
|
||||
"0x28d2e7c852de8602a764ff693b6881af18ddadd67fc7eff481f48ac20ebf32f6",
|
||||
"0xf82e09e7916f61b5cfdc3dcf193bf9d535f2b33f93a06c90fbdc78b3aac6b7ef",
|
||||
"0x626f3cca9e1a9e5e123e34485c8697c758ffc32213a727665065dd6abd2babe5",
|
||||
"0xb7f1c07f673d903daa61dec649eb12286a7a0568ee36ecfb1023ec41427c8dd0",
|
||||
"0x8d1d42bfe88dbe4c621cf68d380dc57e7768121a815546bb4aab29b7486da9ee",
|
||||
"0x79835acd7266bce85978f481aa3c58f3bab9106d72892df8579e472dc95c6899",
|
||||
"0x0911c9c804bbe9be0aebab6c92f5b71a893f72a9d0cd35a51b0e8cd19ab0c02a",
|
||||
"0x7fd2eff10936d8d12fd9a1c6d27e77cbec4e48253465eb7e65876134ff60c8ec",
|
||||
"0xc739ad4255415e2831c6996673f3d02dc79f6e6d6822f7dee23bff5b94833c3a",
|
||||
"0x2559faafbae0852fe5a1c924f0e4f6ccdf4fd22f483148b3672a3e7b3692b669",
|
||||
"0xca37f0aa3d375dbddc0b426c9564fe68f10b0a4cbbf1ab87f97b27b44878f2fb",
|
||||
"0x00ba40205d1bd46ad5b5e73cd5b1f3418bd892586d5a4647ac9a6d158f15bd93",
|
||||
"0xfa6d25c829299535e6b80af81a2416d10ed6903117e73c656b979a5f5abe3ee0",
|
||||
"0xfd82d8944315cfb228a8fa416c18ff82cbd8869c3babbd3389dca6dd66797785",
|
||||
"0xd8834cc29788cb40ec901725419df8c031a13e190756a6352696de870eaf4671",
|
||||
"0xdf6843a52bf55e0f4404e7bdf144bb17d5c47a72ef9482e712090ac9730a7f52",
|
||||
"0x4c2c562f835966c72985f7cca89a3b1a7b0d4cb04623dc96e337daa35a2f5925",
|
||||
"0x49d2afd87e83a04059dbf3ef4e2598b8d0c495ab1cf91ed3004e16a608e910c2",
|
||||
"0x5be64774739c001c239efae1ce9f2a5706cc6e3054ddf24b03c09358f2f4852f",
|
||||
"0x678f789dc8c409653b36f4d2015338165d3bc6a73f2a77ebfe438676b8412d7a",
|
||||
"0xf87c8fbf02d8e84cf72680e6b9a8b8be39fbae9f1eb1047c536d77535494a301",
|
||||
"0xe2428b952d2c6d60d4925f56b3d8227cd6bc608da2c1b20264befd8b1ad89454",
|
||||
"0x561a95eb50c663462bb8af3aab336bd745b0571746b10fefa791bc11be777763",
|
||||
"0x6945f40e3499d2769ceecf499c701015d93fddb607720b18dbbd5a6a2aa46639",
|
||||
"0x9c35b0367a2b82270d64f11c5299336b21b9f454077dcf7af3b2e434677a31b6",
|
||||
"0x454dc6bb2443509381e478f1836cb36808e2ecd1a9944072056c292b710072f4",
|
||||
"0x0c80566f34a46477592560a883a9c01fa393f7a2c9dbb28a54e46a5c017e8596",
|
||||
"0xeff6a1255090509eccfdea2e591516886c91191f1f02eaae4808ac95009086fc",
|
||||
"0x37cf60888e5ec75841e7f0533feef7200185a1c9f3253073216d83923c864829",
|
||||
"0xb169ebb9e418809a96529835bc293782e4fc6310dba450afe3e95a7abdf7cc01",
|
||||
"0xa3c8d5c71ce0477a247f56bfe95272ea07f0b7f10a8526b6e3ff9a8de8faa9ab",
|
||||
"0x2bf18db4ee84bafbbabaf05d1d4d383c0d5fc91be6ae902334496996eb3a8e48",
|
||||
"0x6c116f0d5809a2c28351a737ef3dbd1808685e1fd656e37df6b6e524aa82c918",
|
||||
"0x21e2c8e019c687fdb360c9bdd4e3a5133488cd2e0365aee3b823120734aa6f27",
|
||||
"0x20c9a1db9de894ab4f576265da25f391b32c0805c3da76fbfdd0aaf300f88a39",
|
||||
"0x23ef1f43af87be7396449fc1f89d9766c59e8adf2660812293c65a27482ddb8e",
|
||||
"0x04a82d3a4a5e7f2507688ecdcdc300d7fb97aa8be92a671d7d42c0b60fa4532b",
|
||||
"0x99e204c42afd6d4040faad384517d99bd0e077b03310d32223234d2251d6a07c",
|
||||
"0xe342c0c4295665b9e25773fc9998e18c460e723d0a14efdb59c19b27b9c7011b",
|
||||
"0xb654b1b8ede0d54a605cda54b4635d2b3c2bb8efd01ebd416e52cc87b590d4f3",
|
||||
"0x5daabc41eeb6de98336411a03ec0323995e81549941cf32b7e15c765d1b7b39e",
|
||||
"0x5103fc7f0fc6df43fb081b580bb01476f2b1cbde73e4d0f9d1fa6d8427fae789",
|
||||
"0xe2ecf5daba51d2f7b22106033fc43f956bd1db0c5ad02bd941bd3d2b96ca21c5",
|
||||
"0xf152bce5c6d1efb7e22cde72d6b8ca37f556ffb686a13770c5fab46e04837c92",
|
||||
"0x306007d8091caa5baaa78643307f5abf9a5f03996fc072a9016ba6b487b2017c",
|
||||
"0xf57308d0c02c6b8e2416c070554c7e29911fa84ef4cf2d934e2322ca262e987c",
|
||||
"0xb234fe7433d7fd71fe0c6dfc834e4bcbf84a261b95760a6c4eb67d222b9ff392",
|
||||
"0x753059f3405f60da3aa7cd1aa0cbcfa4d5ef4f2a6ed34b853b2c5ab2181fd383",
|
||||
"0x096c6630e821816d9f4bd83fbe0ccfd223282f34aae5a49f969ba30b98c324c3",
|
||||
"0xd3eec9dedb057fbc839c474fc99cb54d89f3f47d896e06e758c98f1cd194b61f",
|
||||
"0x0d44cb2a83b9a3fa18daac280cf08b46cc637d705488fd9400cd7300475d0a1c",
|
||||
"0x2e37a3036db99c4cb1c135f5ca6b527fa13b2e80ee421805b7be5d8b16983602",
|
||||
"0x381e0ca505308b7d3a083e60b0f9cb44c89f84942430ec9e4c5571796ab6a8eb",
|
||||
"0x90b04d35906c6f5a59c266c3bce7c2b63cea1486f714e272592ef9ecab25b0ee",
|
||||
"0x9cbea70e760f2ee97537d058d57f395886a2c3a6e769ccd3433b797b8716517b",
|
||||
"0x4e2167846e8d6f0f6495b5f1443f59bea143b63f242e40186fc6429434d1136e",
|
||||
"0xcaa0512739d000bb9783fceb46d0427098886e2b7f2e1140855f1a91f843d5b3",
|
||||
"0xc14df4e379e84591f618e60b5953aa6764146c7822aa1f0e3c2287e20753985a",
|
||||
"0xf4443154c04fd378b2c3812fee84b774b37d6e12778674403fb5c995379df866",
|
||||
"0x1a501c2733cc138fb6ff3716899e08dbcd4d75edc18af8972e8a749e45eaf67a",
|
||||
"0xfc8cb80bb0d0fb490f29aae3067641eef72e9225c558e7e299e0796a2086969d",
|
||||
"0x2b7895550febf03070485c02d521e7ddd80b94b7fe33a60b7d7ea3545b13e7dd",
|
||||
"0xfc4137c3cccd45050b5770a40b2f38c43c62b70b07d17bb6d762b405f3d753dc",
|
||||
"0x86ed22bbbb9fc6600112b91601af4fff56d0ecbe9b3099f91d4477cab8e300f5",
|
||||
"0x2273a60405ffb04bd024d880c79010f18d58e3c8ca0dc82795a0125364679fa6",
|
||||
"0x00dfbfe7be3bb2116d9a603a01ac428c0088a2c1477810cd5d3be0d1bd86beab",
|
||||
"0x7acfb03315585c79e2a47dbe847d24cab0785791f6af7f179fea4f9d6ecb0e0f",
|
||||
"0xbf6a2e20ee1da5eec12b792bbaec2531e20766ba54bac423011c1057215851db",
|
||||
"0xb5e94d1e3ba7363d1d79fb62dedd0b6c26b0485052dd64a7093d41ad2d41b890",
|
||||
"0x9b0cc26f08708814960de8f280ac26d8ed5089a19bcbd2d765059306da22c196",
|
||||
"0x22d8af121d3e395d3cb4f6ee43c06e6292f1b5ffda672d2e40dba69a2885f5ac",
|
||||
"0x04bc174272a57189d76aa17de0f76806e8481f4903575ed8c4df12b042637e0e",
|
||||
"0x06ebd2b6ec4b80280969a92726df5f9cb12d4288b60af617b7040876116656d3",
|
||||
"0x0e9430513e63b5173271c89b1c91af0b4818d5d14a3034e1228c56c94186a109",
|
||||
"0x8dc5422ba98d9e58112b052a00d4b82b1db32e22dd7ff2d845619899bd47f277",
|
||||
"0xde513d40bdbb1e4956b468cece598d77134626a900066b92fb2ecd6fcb5f81c2",
|
||||
"0x90746299ec75af1eb444ad14ac666ee444aa020fac3fb57796516d8772ec8f45",
|
||||
"0xaa91c30c62b24f943ee1eec7586b682289541c0355c2726e44424da8686ca24d",
|
||||
"0x76eb68baae9fb7ed126097f93842dcadfe6e7188d61549d9c0922a9b3ef8e80a",
|
||||
"0x5aa5b4045e7fe71559a6e93f4a89b135eaef38b9a7f3a84e383ab1ff902ceca9",
|
||||
"0x504b78f8fc3646e9722e96a5e97d99f2560d4fa3337fa5faf1cc8c8a05f3520d",
|
||||
"0xffd7a5d7c3b21e8144f7678a9ddc039cf85eb32b09000a600c9f12aa7d6083ed",
|
||||
"0xcbb4010000e96ff0b50b9627dae032bd50782ccbd51af8af7cfcd6cd184675f7",
|
||||
"0xb96fabbdd02371bf4a6a0dc00e3874cf43d47246e27163c910c141b6759a4249",
|
||||
"0x7358419f4e994ff296a37f2e88b238b3de6ba73062073c9467dec52a2df64422",
|
||||
"0xca90be9f190a1fd0548becfa719a6e4763e92de0e4da4283a33b5f7d2886b425",
|
||||
"0xa629364f7d6329b008d9c6a0262327bcc12953aa515cdb7b8817e7fe1d746d46",
|
||||
"0xc5167bd8cac1ea6d14f305c9d4fe075e1875d96353e5236473b6daca5ae9b4fe",
|
||||
"0xaf4ce2490e9504172a4393cf14e691e947c86a0ec7b53416384a5832b213d6c5",
|
||||
"0xbfa4853ef2eecc5d99a90e1abfef37ca10c1f823c1d0ad59a1bb19339861241f",
|
||||
"0xbb5a6584cdc7e4d06ec5fc1514233cc42970f6c332c3a9590978dc9908e58c0a",
|
||||
"0xe69d7a0766db411e504f09a8f39f0583b2869016bbe95f21dba432bbe8b88442",
|
||||
"0x89cf4caaaf200881779f5fa6da8ae91ff1c962045dd0622b5ca65c830d3a9d4f",
|
||||
"0x82d66c631f4c4167e5301d896dbdfe24d8245b1de041fc85eaeb6e35117ed9a0",
|
||||
"0x957907bc93879681d8682a188622f9bf2c7d2595dbe3e2e34bb01711cc4124d1",
|
||||
"0xccb3a3380550586696abd3ac267e85c7516b2b682b3c48f66aca94d57500f3b3",
|
||||
"0xaf56d4650406e70748dc860a7879d8d522599081f8e7011056c976b860703e43",
|
||||
"0x5d96ac1d2dff8a054d880a44f5d45a1bd18aba29085fcd633b0608351ff1876c",
|
||||
"0xe051736dad8b9f93a8f1c13031c2b63249925e152685a2e7ec188ee089861b20",
|
||||
"0x0db8987339e1fae41af5f08e6fa15da5fd80de3431b54e82cf8edbdc792f870e",
|
||||
"0xcc99097678110af2be8dc07da8d642dce928b7d9e2728fe6fef1fe2eaa81a72a",
|
||||
"0x2428c1f94ca57c7913b011a68281eee9ee4855e4ed2c97e34a370e649b21acb1",
|
||||
"0x501ee9580c89b1f67c5b3b69ae5fd1f83852a2f9330f53565bcd04d8a7c0b776",
|
||||
"0x16ae47cfa19e8046f93a579fa2557b17aeca7892fc7a82b6d539930c8b7c95c9",
|
||||
"0xda62590043ca70c1cdfc7969cdfa853bddbcef0ef62aabb9f372805322511014",
|
||||
"0x481b4aeaaa60504c94dcfea966840b381db85183c34cd25b4857300b5c189003",
|
||||
"0x035dcc47f8670a9f648bcb0232e42fd4876243a7a3bf737b88d723ba187929a7",
|
||||
"0xebe9bf09e3577865aeb341a06f67bb6e607f10b04ed9f9d733492a9d0e9ceb1a",
|
||||
"0xad5d85b58af6aef7f81bd6b2407c6e4884ec82b2ae2aeaa24e379a3d35902375",
|
||||
"0x0f0dd63d7c6c284659283825624140b31a3adaf7cdbb2255faca443e52ebfe84",
|
||||
"0x40079be1c9394e95b4823895ed380d79333ca2085aed2abd0d766f84d21b7b42",
|
||||
"0x7cc40ed01b436ce225a3f9c5c2bc7f6f81aee40bb83a54bca2fe899b15f3e2b6",
|
||||
"0x1b6356e1a83ca5b0eefda1fd62fa959b118d2a19a6a90f182a53414b3fc7f9f0",
|
||||
"0xae4a71712cc96a5b30b45e3b92c339c2e975e4ed683f4d1fcadcdc121ff7c6bf",
|
||||
"0x226f6d8c71ec32c5eaab6b01c0fc1d00ae95e60b383d09560e90549b79eb1447",
|
||||
"0xf3dec779841c9384df93bcefbba8700a292b570b29d286a7c9c5a442b4788a20",
|
||||
"0x63ef48e80efa45383857adcb0f31076393260cbad058d1938345ad13faae50b4"
|
||||
]
|
||||
},
|
||||
"nodes": [
|
||||
|
@ -143,7 +143,6 @@
|
||||
"eip161abcTransition": "0x7fffffffffffffff",
|
||||
"eip161dTransition": "0x7fffffffffffffff",
|
||||
"eip98Transition": "0x7fffffffffffff",
|
||||
"eip86Transition": "0x7fffffffffffff",
|
||||
"eip155Transition": "0x7fffffffffffffff"
|
||||
},
|
||||
"genesis": {
|
||||
|
@ -23,7 +23,6 @@
|
||||
"eip161abcTransition": "0x7fffffffffffffff",
|
||||
"eip161dTransition": "0x7fffffffffffffff",
|
||||
"eip98Transition": "0x7fffffffffffff",
|
||||
"eip86Transition": "0x7fffffffffffff",
|
||||
"eip155Transition": "0x7fffffffffffffff"
|
||||
},
|
||||
"genesis": {
|
||||
|
@ -19,7 +19,6 @@
|
||||
"minGasLimit": "0x1388",
|
||||
"networkID" : "0x1",
|
||||
"eip98Transition": "0x7fffffffffffff",
|
||||
"eip86Transition": "0x7fffffffffffff",
|
||||
"eip155Transition": "0x7fffffffffffffff",
|
||||
"eip150Transition": "0x7fffffffffffffff",
|
||||
"eip160Transition": "0x7fffffffffffffff",
|
||||
|
@ -19,7 +19,7 @@
|
||||
"0x00a0a24b9f0e5ec7aa4c7389b8302fd0123194de"
|
||||
]
|
||||
},
|
||||
"validateScoreTransition": 1000000,
|
||||
"validateScoreTransition": 4301764,
|
||||
"validateStepTransition": 1500000,
|
||||
"maximumUncleCountTransition": 5067000,
|
||||
"maximumUncleCount": 0
|
||||
@ -43,7 +43,13 @@
|
||||
"eip211Transition": 5067000,
|
||||
"eip214Transition": 5067000,
|
||||
"eip658Transition": 5067000,
|
||||
"wasmActivationTransition": 6600000
|
||||
"wasmActivationTransition": 6600000,
|
||||
"eip145Transition": 9200000,
|
||||
"eip1014Transition": 9200000,
|
||||
"eip1052Transition": 9200000,
|
||||
"eip1283Transition": 9200000,
|
||||
"kip4Transition": 9200000,
|
||||
"kip6Transition": 9200000
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
@ -56,8 +62,8 @@
|
||||
"gasLimit": "0x5B8D80"
|
||||
},
|
||||
"hardcodedSync": {
|
||||
"header": "f9023ea070413bfe3ceb9160c7dee87bf060a0cc5e324f7c539cfce4e78802ff805063b6a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479400e4a10650e5a6d6001c38ff8e64f97016a1645ca0f8ac12c30b4fd0d27a1a50c090659014574b554ba6e9cdb76f57efbcfbd390a9a0b474ac6cc4673c17c5f511a8b43cc44dbb01bb028735830163667d7a3a2582b9a0bcd44b7c04fa24760df7d733ca8ecd99e8da89de0716e6017fffa434bfd7519ab901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffd83755801837a11f88301d8de845b27471c96d583010b038650617269747986312e32362e31826c698416c9d1c7b8418bc805f23fb01fdd498b37df5519f49691d65160fe6a6794b8106e2ecc4782407f0dae3a512546b7d93e89bbb2a761c750553deeea1f9401231f56ae0ccb059201",
|
||||
"totalDifficulty": "2566410291882451733317698215999610733750372193",
|
||||
"header": "f90247a01865856fb6e4118598117560df31734c74cf725c8edae4db941055ac0afeb207a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479400e6d2b931f55a3f1701c7389d592a7778897879a054563efd593e9682943065880710af9187131127148575efc8bb51d80dfed41aa0a568a1653a6c7d559711be0b91a8e75db76c678dbdd286c75b88e4f0c0d31171a0dab32c5cbe9b9244a7af00afa7f6042a4ac923573e8f2f025b107abe1e3da999b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000004000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffd8389b001837a120083046540845bbd803c9fde830200048f5061726974792d457468657265756d86312e32382e30826c698416ef600fb841387b51dae8bc8daa6cde190d3f44797690b4da1ce5fcfcd54bdbb2a6ee6d8c1f7649081ca28b5cd70067ee9f61e27d8184db83705102d5e1a269f2b631b4d5db01",
|
||||
"totalDifficulty": "3020091077015059097853315484608800838133866777",
|
||||
"CHTs": [
|
||||
"0xdb9557458495268ddd69409fc1f66631ed5ff9bf6c479be6eabe5d83a460acac",
|
||||
"0xd413800c22172be6e0b7a36348c90098955991f119ddad32c5b928e8db4deb02",
|
||||
@ -3813,7 +3819,658 @@
|
||||
"0x5d71aff2a12d4f1d05c7f760d07b417a39eb0eaa72a01333befc6a2eb6b7d72a",
|
||||
"0x8dd7de9195d2852aeb6812638ba22e73ff5ca0a8ad921c6e924cae1dd5952255",
|
||||
"0x8f1828b4cdc6c38c112b1ffee7790953112dd2225ec82581a5095e5ae4d71cae",
|
||||
"0xfeac88ae6c8529e87a55a259f475b7d162d01e8fa5f36c90d4665dd6105b1743"
|
||||
"0xfeac88ae6c8529e87a55a259f475b7d162d01e8fa5f36c90d4665dd6105b1743",
|
||||
"0x2e37011bd97c6e8a24e130fdc2c60c39b14ab3eb426a4f654bf3158a19aca88b",
|
||||
"0xdb59b565de21902c50e2e204374ae1ce487656eb74145c103a86707b45a63eaf",
|
||||
"0xf75c26a7214acf2d050ff5c7cc8b76e1a90540410b5c8b2bc9edbfe8fb2268e6",
|
||||
"0x6ca7554f2abfd22951bec80f9d280abb6f060dde4a9a829ff7a0457d67a99edd",
|
||||
"0x0324bceb8b61fa7092396764d7e1933697806c6d785446e3bbab3fc3be0ab259",
|
||||
"0xeb4880f177e3e673f8ee04be1451a38bd8a2c0bac681d82a19327ae2d9769d32",
|
||||
"0xec6a868cd9fba9e4f5b0d4276f44aee71056fbb7f425f717d0ce9d1fa5442ded",
|
||||
"0xdc12b36d165eae197487ec930e35489545d2867b6fb9f8604d279337b6a8f949",
|
||||
"0xcf1241b1c9b054df34638e99447bb0359aa01ad13c38650b872f2d727e6f68f6",
|
||||
"0x713765e9b76c73c2de58c480600a7125972246fdcce2324993cd6bbe49cce67f",
|
||||
"0x81e096e97dd8bf1d206d0ed41c9feaad24d344323ff74707112ee8fac218994e",
|
||||
"0x8943c2246d5ae3e8db5fc012e9613642c6b713e5f2a89d00f09fa73246f88d5f",
|
||||
"0x5b2d0bcbd893fab4e58d4ef698d1e8d3001799b61e758b7711f319e2b8eaa645",
|
||||
"0xf3e4da2cf4579f52b7e4d632d93b79714487ef179a8f5d5c46af9154efad20fd",
|
||||
"0xa2348ea2cd7a5a32779e9d292a9428fa475fae790f08e42f7699ef5eb2489188",
|
||||
"0x62dd923966e02db7d0d27cfdd4aeac081f9827288c8b54d9f19035331a109f53",
|
||||
"0xaa1aafa8f9d9d3e0668eff761fbfc2657d1e1906c077d93200ec000643c6c272",
|
||||
"0xbf40cb21561989004434d6d908451d5b63045c89c2ac9b1eb617ec0054dc18be",
|
||||
"0xdae53edbb07fe84623451da0e25da631ad3465e5bc12ef8fd8323c8a72f57130",
|
||||
"0x685115b38f307f984c7c90e85d167d62b0ec2c924a0bca5f23b1cac12a8f72fa",
|
||||
"0x2ad7e8f86c872504d7c2c48b0db141955d770acc84222fd725ffbd2dc4095b1d",
|
||||
"0x9268b3b175aa6025b959b8fcdb416c39dd339e6f1fde3c427bd1bada36e4384c",
|
||||
"0x502ee814cecc8454abb95591b0d07ed5170db94af7fda8878b9b4287fd68c9f8",
|
||||
"0x6b19baf6b7eae36c0b1d2754645ff282fc2905802ca6394ac00bc22eb1582eb9",
|
||||
"0xecad17ae39f897ab38850cac40480b4fafcafd6624f8fdfcaa69849f3fa101ec",
|
||||
"0xb0804719b391b4b5f554a49f99df3a9d1c3a9884cefc268dcb27e3821aebe385",
|
||||
"0x3018401c9a31f97881852c1bd65a964bfd3011659725c849a8de4b5ad8f26490",
|
||||
"0x48a6b687e62a42dc44ecb56f4187e293d6f87d328b1edf409c8f2fa6568dfddc",
|
||||
"0x8e3bc1ec926a68e22ed525485186a4d9160a54bd3e80107bb77c09911564effa",
|
||||
"0xd7a7cce632e1746120476a3271ea09689380eb833d5538310fa0029f9174e0de",
|
||||
"0x7bae074c51f3b547568d18e85b73fcb9b5f8040ed5f96f3523f53197150517a4",
|
||||
"0x9ba39f376b9444dab04e0a52e4728ec842a0aa4880d9aa9819de3f0694f46e60",
|
||||
"0x40a2b84bd3d05d28d51a39deae5f23b4f7370c70ac70d1cc81224eac4939d69f",
|
||||
"0x2b9f57c8c43284ba929df8f896a966afbdd341f145b6b2b2fa98382950ad915d",
|
||||
"0xcaf3d2a336cf17c9b2d7116a14e654bcece012b07bc020ac30feb71d7f6cead1",
|
||||
"0xd3b68cf2337ca26a9c4bf6b6b286dc65bf66641d5e9c241f4c1b147994253ac5",
|
||||
"0xefc11a5944a8061c87f274515e810fee13f4c350c625a988c27ed276b6c55b6d",
|
||||
"0x7a93732151f7145059424aa823b24e26341cfa57f612e6de3bddbe23562ae918",
|
||||
"0x2594b625d0f5ed52425ccda4e7898a8a554300791027af6f3a19239a15868ea8",
|
||||
"0x1db00091145b1b0830983b5eaa5cd3d0e4ad71c09d1b2dc20c47815bc2de5917",
|
||||
"0x60563bce11f028691cf78da7326f22a4ab01d980020e61bcf2e4bdb5912b7b1d",
|
||||
"0xe6515bdf1f22469a4218f54791d12698d1bc555b3e54b04cf46b10effa8ce74c",
|
||||
"0x990831a56958a6bf131697e2f35ab2a45fa228eb7435c7e65814ba28778d513f",
|
||||
"0x1b6e4085f0e291a8ee4d7e90158dcf15702b4e6e634d1d3bb5c4bab11bf70068",
|
||||
"0xd0d4a6061bcab0f8e645ea16b285eee7f2ff84c7765d7543aa318edbced2408d",
|
||||
"0x2da1a609eb1b572a47f187dd5a1e9f4cb1e1885c841f91ca82137e01a9eb4288",
|
||||
"0x1293686df427f9ee1c2116000735642b3d09511cf2889dde21e1bee427d8c273",
|
||||
"0x8a990d66370eaab3a46d9e4fa9b7d0c621020cd3b897d9e5b3e5fea6a6979f3c",
|
||||
"0x10030534d5a06bce47d72998ad4c042f5e445a505920723d14b1d93a3a23af82",
|
||||
"0xf29a399e8879386e4c2bd8e873dc8aed612cfa8dfa9e5b56f9c51d4c4d1774ad",
|
||||
"0xb252062ccbb11c3181338d9912ed0d4dabcfa4d61860c211f2f702a641fe936e",
|
||||
"0x822c7abd11b80c862bd67d39e16a208c8462936ca86b5cd5dd20c51d35cbfbb1",
|
||||
"0x6b62aea651f1407f94906db704a364f70d827e0efba981a8515d1f515a46b266",
|
||||
"0xa57b7661c0471cbd7eb35becdf468622df8338a48a075b722ebc5550bbf6b9ae",
|
||||
"0xefc593d38afead5ee1fea5d8b41a52bd2a5b5a059774d0b951bb7eadaa41a46a",
|
||||
"0xa556e684c26e7fd6f902b82ecdf721fc292c35e0d2240c1f362c4861c366c4c6",
|
||||
"0xc9f274efc308d1e97ba9b59c92735d1ab2a72d033ed02a543dab301610e96e33",
|
||||
"0xd7b43559126f88c59392fc54e2b416d2a67014abce12ddf61764df989a897bd3",
|
||||
"0xc860842132de3d8c1d0ba2cdc0a7c2853ee568789f1190738862667e3539a958",
|
||||
"0x2f330354084635eb507cd54549ab89fecc41886d295b1d8c91efd8ca27fe4f7d",
|
||||
"0xda6edc97997b9cea1bc90662c6a8180fa03cef6189e09c86f36adb91400abe74",
|
||||
"0x0d2853b5a3f02ae9e4a1c5a0534a5329d2e877d4d77f60dddb36b84b4fdf7e2f",
|
||||
"0xf048b5acc9e9191ce0ab8c390bfe03d89cbed91db5b9e7c7452b01bf56bcf5ac",
|
||||
"0x30fb6f6093bf59794d37ddf850c315dd9491a4cf5df378b4468dca96acf78e77",
|
||||
"0xa04eeaa9d1d767c0f93553af3a259390a9576e8b6015ffa8f0e4fdf37f41f28e",
|
||||
"0x02411cd53ac55407e0d31520a8c3274a2f4d1fbb2541bb140f30f25843c76860",
|
||||
"0x65bc790d632d5fe2446c65325df875ba59af3c3aa7357bbbbf47c7e5f7663a7d",
|
||||
"0x5f364562fed351d932eff956c3ac489ea51ad2cb12a81bd8db4fe0b76e3cbb92",
|
||||
"0x104f7070d5da1aca5c8b20a96d36638e4b5f8be4e86be83f0aed7234fcece445",
|
||||
"0xb2fc7a73d8d859d531e51532928671ea59ae6538d4572fd5c2d76c70920aff7f",
|
||||
"0x7ebecf446825dd0010fbf47afce8b9c3b3901c839ec46269eb8744bd799699ca",
|
||||
"0xc64002b5a70f18b7c51ea3d3f5246fe8db16781e146d777aaa12f3b765d108e9",
|
||||
"0x9d136068c7002d2780abfefcaedc79424d3e89b17718ec369d9e64ab7b63a81f",
|
||||
"0x7b9819e62e92dcead89329bcb3f1a1d6bd10794d1a22d30c3d0369a264029543",
|
||||
"0x8a8c9e66f343d09d5b7897c491c851143ca4f337ddcb5c2b1462b150e22c6f47",
|
||||
"0x9d86faa1a5d355d6071e09c8cca50e2dd7e7dc117c2e4f6c0136a2789e84aa8b",
|
||||
"0x234e156c10a80422ca1aafd49d614e02b698a0d89a7080f87db5dd5169b419bf",
|
||||
"0xafbb572b8d9119ba8126fdd5a593663db3a3e6165a60f1f439902a6321a8d243",
|
||||
"0xcbfeb8af8c93b11eaddb05df2f2a8772da694f9cc16878d3154d0857f17274ae",
|
||||
"0x7253cf6bd2b4d158c2bd60acf5fda9dff6cbc6468ca9b549efcd824410d2e719",
|
||||
"0x67fa14af20fe738ec5c9414401149a1f198207969768a5b982454146ef720b85",
|
||||
"0x6c0ddef53c7d58839c3013f2accb72190b7dcc52fbe5d71f4a20f849dd72725f",
|
||||
"0x89e77c0dd9fcb4b4d4d10c25903ff5b905f5d64b6bed9a0736e9dc2035ade3eb",
|
||||
"0x42466344821fc29dcdb5fe7dcbda00b3779736ca90f87ca1802207f61633877b",
|
||||
"0x6e2303e8ed41e6d39488c57dff8d50c548a7079a26c3fb86d925c0aca5b8f67b",
|
||||
"0xb8a14969606442bd94048f2b2dc7b87662d801097537f51c8eb8f026c52f1fe9",
|
||||
"0xd7ee25e0bfd080d89c475942575fa055ce5ae268a6f01b916b399f6ff7e94a39",
|
||||
"0xaf5e7da13dc0ab08ba5185074657acaa2ce753a20a364f3a97d230c247bc8d1c",
|
||||
"0x92f9106bc9ccbb4e0b4c0d1b96c5bf347d856884eca91a0bcf29e896789fd9c2",
|
||||
"0x4bc12bfadacd6af0737646b813b1a4a9c005e97ef4b090bb74b7475b50c85dfe",
|
||||
"0x91e4ef72d0bdef33e2e2c8acbdd7926182568f559397bfc086b96979e7c4f53b",
|
||||
"0xb2f57e050021b238e0b47b0b46a641644645db5bbd987e8d957038655d1fa83a",
|
||||
"0xaf221401f4cfa3db7879237b40c68300060df9f65dbf68bb02694837eaa8af7a",
|
||||
"0x2dd280e98a0d6bc950b7f3f0bd11a9e74105d4d15463184a3f8c03d40f3193ef",
|
||||
"0x2538560e5b802a89a021685f994acbdb3181f25d0cae17160aedfc619ca2954b",
|
||||
"0x133cfa3f5d6a00f7392a6b0c6a97a9ba10ec50b24cfbbe6028995258cbaa065e",
|
||||
"0xc120807872f07adeb144905ff323ea79880389a2815f8441befbfa82835555b2",
|
||||
"0xa2c5c5a3cbf6db506dfc13285b07c24ca7e70d9e75d80fe711c3082ba119d77a",
|
||||
"0x837622b7bbb8bb18b3d42058426ef97e3fbc2842d2b64b339733b52313557562",
|
||||
"0x29eda2468556699747beef75f015e6772980056cf367b819d05a4822b7d54712",
|
||||
"0xc6ec29323368dc29a1d4c3c11e945ef7fdb56db78808c4c9688ab5f9eb7f27cd",
|
||||
"0x44b368ab63e1fe0e0da031a4e6628ed1a4fc69fa4083cc056dd9443400be3326",
|
||||
"0xf153dbc5fc03a89e80d2808ecd45e9fe6453d112508d32ffc6305d5a577d14d8",
|
||||
"0x32452c0d51df7a85eac3edec46bbfe376c971ac4df4512d7e050e6fa711373ca",
|
||||
"0x70cb25f3d60126cf0104a40b2a49b44ef8a42f60b93f929594938ac00647b639",
|
||||
"0xed63fb33d707b93e45e958d5d5f9d3f0898c3676e43eeca55c788cbb2df3170d",
|
||||
"0x93ff103a026350b0e9c2b30c36e079145892e8e3756678e8ae4b0065fb6a04ec",
|
||||
"0xa466cdf6063bfe155ed75c115484ce113227385eff2cdc07dd90405239842f3f",
|
||||
"0x2883c296d9ce6b1e6e7b4f471e841437603ecbb867570cbc46d86f0f26871600",
|
||||
"0xea5e5b84183a3a709a51c1c6f3e7b039c4663d7495b9bdcfbd4ecb0a95ea994c",
|
||||
"0xc0e97318bd3ee2957c09d6acedac77ce6b219608e5dd63ef512aa08d63c3a114",
|
||||
"0xd3ccc7fcd24076afdf6249f671de402b515a131913df2da17118be47b3720b33",
|
||||
"0x4f5be5a6edd66ec496207b33cefd00722f3167b9e6f2a44d9613c4c7d6541aba",
|
||||
"0xfecdd1844517d0523a7b45d7b51769728902b881b7fc308f486e850c870eef5b",
|
||||
"0x01a22dea1d0e25885e0a03e56489bcaf6747e712ceb5a42c74430fa6ffcc1c21",
|
||||
"0x06cc521a05ce856dc55041b90dc4bbafffee578c1c315b5cfa4cc2d1ccba891f",
|
||||
"0xac21d4b08fbf2891e0b3645b870695434fe703101f74e7fcf0d0e1304ce65b54",
|
||||
"0xd62584c47aa1d8554cc08cf675bed128e541df54900fbfae958877595ad168ff",
|
||||
"0xd8f1806ddaee8e729218fea1911efc5e663666ffb3acad4a2fda3757700d6d88",
|
||||
"0x9dab2acfe01506a185276145deeecdb5c8fe0937feacffd40fb25a83e8eecc72",
|
||||
"0xf0b74c6b1a441fc2ee8b2f25d2f03307164014d42a0784683a9d6cb7d2179064",
|
||||
"0x7d590f0bcc891e30996adf8583803a9dd1271442c3f0e69502addbd371437767",
|
||||
"0x3a66601fff95b0aa0d0660c12788ad56d2383cae290ceb2fb9ff41794abbc55a",
|
||||
"0x36e94b03402f18c689f5234973ce1e626a82aac085dbdd682b51cce21f8c1872",
|
||||
"0x00abd1d34c7e55f58681866558cb844c11faa55e8cac70ede75811f55341cfde",
|
||||
"0x9983fc20e63e77ec0680522035b03167403681674ec62293cd6b7fe360c69157",
|
||||
"0xe98b658fb8b6b7fba7463562f86348bf1e3534bc9148e8559423b3ee5ab68472",
|
||||
"0x77ea189d3a408a8c5b1792881d93ba7a471f90a976ed334cfbdf865ff94cf20f",
|
||||
"0xfbe2fb93b3ecb384679870205f2be2f47140f8d832f841ba8653e00d68056c82",
|
||||
"0x330f5f04314ae57097db5258d861b993cbdc2ca0522421917463b94636a99d1b",
|
||||
"0xa59cbefffd0e1cff04bd4004d21fbb64c4ca542b98220487ccc79a39a6a0fba8",
|
||||
"0xe08f21b0f5ab216c1009c904939515d0ef8d8ca80f8c3cd5465944bb6550e728",
|
||||
"0x37f1db42a7e99ea8b6d7f9ec5bfb39f9613cf79d98345816533b85726c64dab8",
|
||||
"0x8c226434c5115b7ac0f894d8c4389a1e38a3118fa0993b59a42291286b85bd7e",
|
||||
"0xa9977dc362eba9d32d13188dffa6cd0178e0b8c29cc24a3c04cd6cb0781fc133",
|
||||
"0x502a68fcd1c187d662ff6852179d7602b04b5ec3141ffb39841b571bbc6cce25",
|
||||
"0x09a716a32626ad3443d7f5f6e5fce5145e8b962a531464e36aae6356ae93b15f",
|
||||
"0x2c165daaf0e8a4433d8bf97091bb573f1a7cbc7e82f2af353af9c580fbffa8c6",
|
||||
"0xd8b47ed7ed3bb85bf44ac2b5e5916bbb282353f71dea6e172434f05cb1276c4b",
|
||||
"0x2bff102b5209c88370b2deaf941653c364a90b39a6c3402336b8b3c9b47731a9",
|
||||
"0xf6011e416be00e243d9b6b57df1bec2458d271b2a8a964292521f6f8bc7355de",
|
||||
"0x8f4a6d08359aa81c14391d8483bb8e621c24bac1e32b2c5c505d5617487bd06d",
|
||||
"0xd2f89aa90547e1956491879dd5924a50142d76460532f00423cfe70f36546873",
|
||||
"0x929b13fbde5275f999f145a273219d6f7f4c25ac29b4eab3f89d68305e7f4341",
|
||||
"0x1e7e79d55594c3555eb7d90e4b5bcc8b59ecd98848884b81ac5c2d53bebd5cbb",
|
||||
"0x11c2705c4a89fa9187f63dfc7a8bd4e2c087d6e937e777393f1e2856f6f00104",
|
||||
"0x294b40af144ac5046bd2a5451d1cc9900858e0e351f3f78b50b2dbc203111600",
|
||||
"0x26432c2ba81f919c085a4d2326c22bac341c17f456d8a93a1971c0fd741ea79a",
|
||||
"0xc488baa35e04ed6bf20753fcf856f31a98c00be65d51b73c6a5490d18fb89d71",
|
||||
"0x915e1768627ebbee21159a0562d8a5df69b05f057fdc8b4bb69bcadaeadf2ae6",
|
||||
"0x2303b2be6801e3fe8c02c0d0355069240da4f617b47a4ce6bbfaaae56a1e0915",
|
||||
"0x0e4af9d5e2cab6a62d9203979db08996bd1f111a315049859e2093e83e465262",
|
||||
"0xe54756890992736382616fceb3999d22ae462b9b5f8b1da072277da2df6b5f4b",
|
||||
"0xb5aa407d54e2ea651563333d3d330af0cf45a992bf89db0c229962454c4da4cf",
|
||||
"0x88832a6db2c8c3d899dc59154ca323c08c5eaa8c05d142978490246e7b4ba7ad",
|
||||
"0xdca9619220c991618eca5cb18b1c14c6fe4167614a8360c9e1737c93a129e714",
|
||||
"0x3fad9a66462792be9f771b39b6f64e537683a74441b85b53f9c5e6a2fb687100",
|
||||
"0x6dc5466ae00317d52511d9e153ffa37cb6060639a010c8db25b33aed702b486e",
|
||||
"0x2a2ca3148598d3106bae23b6f66a24e3e93afeb576d283ba6822220780008e95",
|
||||
"0x480f699ec76a16530e382c2e8d91c7edd3ec0d393ccdeb28c7d692eb52b0af96",
|
||||
"0x082d3f5dcff2a41e2fad715d64eef361271648bd976d895b40765089c544b65e",
|
||||
"0xed14dc5ed74dfdda8b45dfcfe99e8581767cac57505805a4945b79e2110bf92c",
|
||||
"0x6890d1a6c90f5c1020ea4439957ea54df3cc22f14e22047f63c9a93696210b95",
|
||||
"0x55ae4e30fc02206a0f389e03c0ef5b1409f8fe34d6a5dbd5487af608e3b82369",
|
||||
"0xa709e308a7899591337d59ea459098364c1d6638202047583851acc5e6df5017",
|
||||
"0xaed8371c95bccbe53effffee29f40a3e9656bc95cceefa364f7191415dbe15bd",
|
||||
"0xa7450bb8e1ff3c7b53bada0cb8ae783e561a3ef74cd3be0d19cb9ac5ae807aea",
|
||||
"0x9fdebd0ae46437e3421d7f0a95a76f47b34f0e0eda37d69c078ef5b44411c027",
|
||||
"0xa18a165a98307fb994401171c41e375a4637fcf2beeaec8c18fd24304b068570",
|
||||
"0x930f3cd1edb90c020c19a6f6a8b86c86981c3ebb8fc19073f09c345fa4b0ea6e",
|
||||
"0xe4c0549658dbbf4f541c60606c8b85dba190f58e5af0bcfbed101e0ff4a8f455",
|
||||
"0xcfd5428494534819ee14e002c69987fc54207917e83a2b6e97a1e1b801a5d939",
|
||||
"0x0cc3a6a2a5de66f64f5491908b5585eb3464fda42c7a58a9100a8cd0ce763b04",
|
||||
"0xcf635d0b4522c64a9b00902770ae33b618580983bb32b94134a69ca8f6c6258f",
|
||||
"0x2cf5c41cf911dff328ef15253a7419733a104cf9cd1846af43d5fdcd914b321c",
|
||||
"0x6d4ea125dbf83b8a9dcba40c4a81673a365ce81dd8eb1fc10510ee7e80a40b1f",
|
||||
"0x9c68f243fdf1738f9218c30664318278afa8f461c13bf5e1bf30133d3fa6347e",
|
||||
"0x62aa880648363c1f3b5bbba3e73dc58566870ddbde0911c5e11aca003a13b525",
|
||||
"0x286a2b6f2e35c2a6900a02d37d82263dc55a3c40d6c40488258af61f8cb8b589",
|
||||
"0x296136ec9fba18ad43a5435acbc3006e52a182aea1e3eb005f25ceaafde2d0de",
|
||||
"0x9ebd2127fa6f5f43a03fcad8dea37bde3893f627b48e63b9e2c6e33af811a95a",
|
||||
"0xe8e58e2b6fe45ba1881eef4ec1e1d954e12793ee68060d50b9c9502009725317",
|
||||
"0xf831613def863279307f637be60e9608179e9a148557585034d20816ed7d5553",
|
||||
"0x9ac311437bfcaa1c66e1c32fa18f8964ca9d9ffe3cb3be306b64519b35051e48",
|
||||
"0x931a4862f94054ec0f96037a225f1c3421ef99d8e4a8f774407cf913273bf4ec",
|
||||
"0x07dead0442ebccefbadb2859e0f462fe8d3e6677c7fd04b0f35165ceb017c171",
|
||||
"0xc4afb80e1dcb56ab83d5b20475d2212b6c55ab63fee058a914661657d2b1187e",
|
||||
"0xe198b8ed96c1b7dcefab5197036f1e5789ea6622dcca2d817e63537b00710b6f",
|
||||
"0x728b8b91918a059e3f46ec7658bc5948016f76ec200d91ec3a163bad8ad6bfd6",
|
||||
"0xacdebce23301e49e068c83a73ad8484d8af7a0c28d066e62787542e154b42559",
|
||||
"0x7f66807da0c2b155126b1d3a69488b10de7f0ca38f6cfe6fa670dce511a1f667",
|
||||
"0xabf510ce1a016b5b3d4610b3cc5c9dec43a6a66f3555a70e1c16cd451e8894c6",
|
||||
"0x56ee11eb3233fefdc056827fccbea1ff2be8a3f460038eef68a1c730bc1104cf",
|
||||
"0xbc4df43d4acd0fc2cea064abc5b5d1754b29073533652448d44c09adc1d32998",
|
||||
"0xf61b97d2d1e537a6d20438f4729bb59ffc8db6b7375c6e710b4be9e136f1e19d",
|
||||
"0xf89f04d5cde25522103d1e175d68dfb4955b4519a5c2cda1a041298579174be1",
|
||||
"0x702c60e25d6a10ac9657553e376f2385cc94737ee292a3ae671ec02af982ad84",
|
||||
"0x5194589410d5f02de764bba1c25da027861793270c956c56e67e017d89323799",
|
||||
"0xc448a3b8bb1b6efed04d84f82d63aa0c7ca19d3cbf817efe4db82b897ad6a019",
|
||||
"0xdee875d8c517db5cf20b745be7ea1d389612e47880657d003c6bfcfdbc8a6303",
|
||||
"0x0528ce8bc52f4878268be5e00b5028c9af85cf61a6279e75240e2adf7b498ac2",
|
||||
"0x6cc80f5c62a1510d9cc97ca8b4c6245938ddbefce782635dde0ca2516932fa21",
|
||||
"0x184f9e305ce4fa0bdb47ad00bc7d10691bfbd7cb13b9c9d4d82c37678e8df080",
|
||||
"0x69456f4aae64f57b3709d6c6701a1894802a4db96374da6b979b87aeaa5e301e",
|
||||
"0x60d1bd0acd9013472acc0b8ce0b90a088f35d5c19645146ed8b3c6330ec92052",
|
||||
"0x09f87c83c6be698b2eff45ffbeef79254e5ff8d3534831c79346e5b837110c1d",
|
||||
"0xc5fc2dab2c43c27132f31a915423a6d6a30a560e4aa266483ef2ef1ac48d0fba",
|
||||
"0x87a147b03150b429b0c86569db27ecde32c1bb9a48b1ea4426d8dfb895339673",
|
||||
"0x1a68fd5e6efa8e5183843fad88d6445fe8b07c01b884f30563ce527e6b10749d",
|
||||
"0x4123e02f2c2869bfd99f3138aac82bcf1923260ac28f33bc4ff2dfcd54c48e4b",
|
||||
"0x452345c2de5fb18422b4327a79053cfff33f277f0e3fc69bf2073d0bda4dfb74",
|
||||
"0x830eb26c402a88c6281b0a48a93ab16a64a8e4244f87d589b471a3ceb4577f6a",
|
||||
"0x84445f1f8805d911009a3e55ebda5e12ff347e5a34d0028ca44a2a26846ba903",
|
||||
"0xf91a600ecc8aa47f838a8d877487c15babc10ff97a5be8bbe4c3eb705fb04dc5",
|
||||
"0x01e749439d413c66340934dce9d4c55179375208069fefbf89aef7c3c7f02bb8",
|
||||
"0xacfb6917a7365046ccbad1ca8fdaccf8164c216ba8d96cf64af5340ee3aec2c7",
|
||||
"0xa1c20a4bb21a0a99f3a38818c05a3ba66e8321f24dcc7ab26487810be8211dbc",
|
||||
"0x7c88ea06f3c8cab9ac0b29376f53fff4b56672a1704520fbe8de0e3ca0bf8acc",
|
||||
"0xc19e59ef2361963b94bb211b8f6c172670ed83fce3d54b3e00d1a82f292d1d2f",
|
||||
"0x386ebf9ab1a551ddaf599d9384e70a34a961ec55d5f609c088c6fdbf38add80f",
|
||||
"0x8a635842c7d38cb2bae11ebe3f6ec09e2d41ef6b7093e4ea8cbf079df97f06e8",
|
||||
"0x2d12afbf38c0378d287693cc7fd49f3e068d454ac5ea7bc76f6b3e505bb09f27",
|
||||
"0x33b7eb72362caff0e54cd853549bc4a802345d774856558a8b128e494ec63948",
|
||||
"0x31eef3a0c2c9f586ad2305d8ed9831619ad6ce2aee9a16800cf4aa048b1d593d",
|
||||
"0xfbeb707dd62204a0f3a06ef9046fba5b3b88fff3a38b5b08cc3213f5965c69c8",
|
||||
"0xc8913325245c39d0609c6af407354e9d309c5d582c8957a90c86c944d2f5c6aa",
|
||||
"0xbedd0ccdb57b01e688c14d6230aa84f5912cf13a72839f654eede63ca05ff52e",
|
||||
"0x0b0b7435e02cbc3654eabd042c32409f4e178cb60f5e306ba041c985378cc286",
|
||||
"0x749b3fade2cbe924b3d76f2b9e216c1675e8687bf7ede81b090ea36a4468871a",
|
||||
"0x9a59125cd56262bf0b6d2393be4ba8f769b9d5a53b644a0700c9905dc4d91c14",
|
||||
"0xdd2001f6cbcaf2d29a7d022e6f723e4691390f56ed6a599cb58bee74c64c67a7",
|
||||
"0x05870eb07cf5d1c1013fedd8cbab73b7341e930a0c02e2dfe898d5299981e34d",
|
||||
"0xef78e2f60d74c818cbf8996913c08a7c5abedb3f0f7ca412737c071cd6a38ccc",
|
||||
"0x636a6d39d02bc22c139d9e203b1ae8b2dc485cb596641ba6e05929296e87ffc4",
|
||||
"0x8cd6e1340deed5cf75bb30c3183807b653c7ccca712f379d5f885ef1a4100945",
|
||||
"0x549d904ec260af5776c241a80c2075e31869b8da7026a078fe158c0b0d646b11",
|
||||
"0xc73927c3be804cdab32e543e78f38f8e0899d7f0418e0b37af336c2bb37269cd",
|
||||
"0x62a4d4dc610995d0f08756056ac199c3f0959674eee8d4503067b822e37bd1a5",
|
||||
"0x4b4a3cb0ac65532d63592978b1afe838cceb7cac04d30a58cd4d73af4b99d2de",
|
||||
"0x2c5aa96bb3b58a76b4acefd0275f9f7f82418501ac2c2052e0a5f43eaa4eed64",
|
||||
"0xd6b8f1a8e502a93e14a8177bd750fb7e7974b7527f50bee37690b523dbeb077e",
|
||||
"0xaf38bbf2941d5ac311f8ab4cec22642049473bb3a8493ecc27cce73dad188797",
|
||||
"0x778b83f79934655d67e52a38c09410e5b5cc28b26f4f70b84d2bdff5519bcc74",
|
||||
"0xcc016a4cf3d1f7119704551809e89c1b4f95d1dfc4cb7f95db2c5d2a6ff1036a",
|
||||
"0x6b904799fc1df35a787bd7b1ce4337697bad98b25b2bbf264a7bc68d452df41c",
|
||||
"0x915536046dad19310976f8d158795e4237bec7fd5c2d2fc8ab1fd6a3b5b75e43",
|
||||
"0xc84167f477d317ed1e6b1452cd746d43ed679f4ff2eae84b1676ae99d3bb0fca",
|
||||
"0x71758a9fb0e66a7a04a076569cd3bb41d5b91cd1cc26b21a773e67524af84e63",
|
||||
"0x54f60d40ea84652f938d2856533d82a7c0b91091a0ad009f48e599a917b52bb1",
|
||||
"0x618cec420aeabdbdedb8afba71b0d0408da5095ea3231455b6c817f9a585d437",
|
||||
"0x57cf387db60cc35262bfa939b0272af7c490720e496b5f8cbbed6b4b26397824",
|
||||
"0x7c8973551ad57c278a0d8702cfed004dac293e2b9464debdc48fa88be033ba5c",
|
||||
"0xc80eed1b2bf137a5574d40252d4d02d0e3f87618c79b764407d8009a2b4932e2",
|
||||
"0x09ab540be725d669810c498557b61a53b343104c5303cccaeb31e518782d64d0",
|
||||
"0xc996eeca57ce9a7ed79f6db45ecefe1710abc4b3e21dec8f707eb5f7632c9c43",
|
||||
"0x160af8ed3f5f55bfe0a9129da94ed002277580b297e29cbe23a962c41eed1cf4",
|
||||
"0xb8935e0d55dad821ba5605607cd6a025d6ff76ac3d9d855fbdb3d000ef864dec",
|
||||
"0x10f6dcd55318225d362a40859030fed3199ae015791ccf4c4bb343e7cb97822f",
|
||||
"0x6f3a76c93761f73bd148c57f2bd00670c20bbd19338b7fddbbca65e598b70ab5",
|
||||
"0x6e99e5531942dde6d881eac1f03c6fd2ba6f9d79b6f88408eca815d84ff48157",
|
||||
"0xb05ebff5d64b736d36b372da80fe28d6e76b64c74e1ca94f1a859936c7ecfe7b",
|
||||
"0x815a140ac8538595dd724ab2c31e13d30c03ed3b64d2cbc72871fe402c7c88b8",
|
||||
"0xf4376c81472e0b3995618f7845887159eec1e929b8a485c2693219f4d5ade069",
|
||||
"0x30ff47cd807666e5ac48659bbfdcf8883fc1c9ea4e9be8b397dbc969a82f8d95",
|
||||
"0x74e35254636ae2f72005ec69e62273e9cb7387fbd4234aa58184e11725e2f569",
|
||||
"0xb4f3de4e9a22e787077a53017e72bcc8ec26a1499c98305dabb61ce6582cbb09",
|
||||
"0x3a05acc943f2b7d0c93cb4c5fcbbfa3ab9e536a2cda7f1c325fe3748401b4f71",
|
||||
"0xd75d428c14fcc7ceb929328989235a5fc46f8ed3e0136d81dfc15866756455a1",
|
||||
"0x20833cf410b3a0626a6c7e07d5fe09bee17b218416725ec3fac716597e1f6576",
|
||||
"0xed31b1b593289be968e483888fc80e5c360beb66626702f388a0848bf104687a",
|
||||
"0xf55fdb35314f9b873a70bb207536eb2e22958ff9264f1e088b0dd82bb9358b2a",
|
||||
"0x701d2b5d8794e244d85366d13fa0382827ccbcf557ae2735bc3f88bcb5c778d9",
|
||||
"0x0492794944f7d179da85f68eec5ce4575a90b7a6f161ae199373ac4685c6c665",
|
||||
"0xb1fb246d93a6ca7a0ce6518a4d0cbaab074bf2ada05fad7a6d199cb830bebf8f",
|
||||
"0x77172f0acbcf0eb3ffc2e314b548210fc74c10826162b2d63195cb984d606623",
|
||||
"0xc9f684762b2378428ebf3dc8e207fe8d2b33c5a0ae1510ef44e2dda7e5979faa",
|
||||
"0xeb864bdea464cbc95b1e3a4be62231f91d1230179b7bf61f755abf5f05cbc9a3",
|
||||
"0x10fb3751407e792cd70fced2271f125d438d9cf3843d9ac6f89681616d0cb1ad",
|
||||
"0x79f96b934d4b22eb9315230c113fcfe0ee2828133e10b14cf2e9b3a8007dd7ec",
|
||||
"0xf8c0546c0c5eb3d9ee16295c5e0fb510a0ff3f55cb654313db2d8ec6195ee996",
|
||||
"0xcdc41342d4045064634291c9bbce68efd7227bc2832b372502fd4907f1957ca3",
|
||||
"0x7c09a67309e6a0993fe1cabb7528e5cab4ba6a79042b22b3a6cbb10778cdecc3",
|
||||
"0x7d5c881d1a199b82608d7e27456788164041cb1e5ece5e3b813db550cb402203",
|
||||
"0x4f7238409440404425f9f60c034696e4713bab4f4e507b76bdb2697d1117ad70",
|
||||
"0x8e8642cc65aae464b068178c4c2276dc8860b63cdd8f3447ba07a0e7a9b20c71",
|
||||
"0x59fd79b1b77ddb040cb6bd45f10ec5ebbc7ba421e14dd79755e568774010041f",
|
||||
"0xc8bfd004b479e0ac8e2e798045343198909a6f5657625028bd28af69de58d9d0",
|
||||
"0xb550f5483d01e8d32258708d82d463f28658d5155a15da214bb2c748e27365e6",
|
||||
"0xeb7de7083d7c73f3f443e6d009e97783ecefd77157b830cab2ae7d41a91b0b0c",
|
||||
"0x6f3145fafbfa23c5667b646b3b5fe12b0fb08e45f09e62e9254efed6ed812880",
|
||||
"0x66cbab429d401739e655ee55de9dc3ee6223230e38daadb1fee88da03c46197e",
|
||||
"0x410eb1081b98fc38f2447bcd358a0996bb9660f949b4d9d6a6596aa41de59557",
|
||||
"0x2fb84f43e9750be8f37cd293742776ec76d95170689710254d7847369626d6c8",
|
||||
"0xf1d6c7c8a81aeb7611531452bc46b69db1b56a31c1c835ec5b497b6f4aad2b8e",
|
||||
"0x1449b942575209a4bfcac57d594cba694bf494e98e154142d5423deb193ad2dc",
|
||||
"0xa14bbe0f97892409b86989212bf815a5024769707bb8fea7479417402a346f05",
|
||||
"0x1ebaf8a3c224720c6cb4079b8e355411f0181318dff7766faa204d4292e6593f",
|
||||
"0x70169dab4258b561057c427b3d31de403d87302180db843d3ac6fcece4a8bff6",
|
||||
"0xeafa1e0854e1d0dedffc92fe173f2333d3a0581199fd3c63ea69356206329d65",
|
||||
"0x54de1a943017c40959dbfc25e318b0055b0e041cb170b0f34e1fe76f41bf2f15",
|
||||
"0xb4ce2d897abe390b9b53be9809fbc1dce8d23c2d726dfa1d0e1419d8caf2c6a5",
|
||||
"0xca872995f8268bb0855fc685e69d590defd10fc6befb61a57ae75255ef92cc23",
|
||||
"0x3e3606562cdf9f8460c18efeca2d7f3649ac96fcd81d2bbd501e73a01c729f27",
|
||||
"0xec09b7014e049e25e0749f0a0899a2893605003f128bca3bfbe92a00c9dbbda8",
|
||||
"0x9421e443b91c741c80138137362f7b30dd9a0db6a815a3b4a799ec12ba6de4c4",
|
||||
"0x78c95ab7995ca6058f64f7fc4af9575923bfa70a092ad2268f0b2a3a20dcc247",
|
||||
"0x386b36edeea33668de333683b1ec3d9c665f150aa96cf78be27fdfd8f185479e",
|
||||
"0xc732d05a6122e07f7566a2a751adf5da1cd1ee23dc0b34c0cfe7cc12f0970c5f",
|
||||
"0x283d97620ed18ac85ab1d2c613d64df485b6efa26aa6efa71f840240a95cc240",
|
||||
"0xce779d27aacf6e512f5b52f96507325568f754b31db766cb4aede53c9e1845af",
|
||||
"0x50bbb90f2a3cf4c479be3e118936246db591f98e37caef06fbee553502b4c364",
|
||||
"0xcdf95c14c577f913331709c5d044fa536a4afbc06cd8d60ea7b5d9ac463e86e1",
|
||||
"0x3a7d03a8ed71d0ef15ed70677ece7a2ea32ad1e96ea5c3266a1d9f580efa862e",
|
||||
"0xda132c0fa137c542b06170fe085b483afdbc97c63b4546079262ed0fe1125c1b",
|
||||
"0xe4cc4056951325ee41cbb70fb823eccad0f266e032e839a2e3a8e851f0a6c73a",
|
||||
"0xc301415694835a5bf36e226ffa42d2fa8069dba6be6becbc2a7a6653c295e8a4",
|
||||
"0x1856c6fbe4494ba46fb87deed5c10e361a83ee73bfbc8f1b604c6fc0301f62db",
|
||||
"0x1b822bd73acd2fed2f8daf6936ddc8175507f373e701217b645cd6cb2ef2019f",
|
||||
"0xdaec59b4c520d6b5be4d82b1b1338a5dd55c9df443d697fbab750c337f6986d3",
|
||||
"0xce6ff73593693f7cda1159724457a2aebf0ca608105a5926fc98afe5010349b1",
|
||||
"0x53c50cc4da6192ddfa851aa104f92c865ce212a87500098d18100394140ad6ce",
|
||||
"0xf015a6887a543a0849a128cec761f10f7d94f7be083f739c767c727aa9ed95d1",
|
||||
"0xa54bdb8a7ce7327aee991715a7d673d403f2248574bbc0ae5aeb9a32b3d9528d",
|
||||
"0x47d46b4777a303430fa4e45305b31a113acb4aeebf205ca215447f9d27ea401b",
|
||||
"0x7a9504b64ca570814194b95acb8400357667122b5b1fa4cef386b35e28de2c61",
|
||||
"0xa63e5964474672c45b8b021b7cc408e30364c163c800fc302f342f119689e022",
|
||||
"0x988eaa51716d4cb523fdd5fed04dcc195c5fe00a8e4b6135fe70b6f09520bdb0",
|
||||
"0xfb8a8f98809114b3d433875844e5fe90cf0321b772aaf86863f96e8013b8de7c",
|
||||
"0xc893ef50496aa272414f6a06af7d53281fbc7265a3e389a42c7c49d32d24fc46",
|
||||
"0x4956f7747cb6489eeeb92b1c759f54d534397074c9cd017b2f5181187248449f",
|
||||
"0x4b48dfaa0b7984d4eea56cc40c5130936f98752e1c2d02762b5caab600c39691",
|
||||
"0x23df05dd92b7e6c024c02fef9cc6aef2ceea2d0a4827de1f87bc7eb4f8c8907c",
|
||||
"0x47ba2e8a2e5d4fd0bb04be0d76a2d553d4bbfc574d1b5c715393fea03672f4dd",
|
||||
"0xa8553d8cc2aa6cfa89c96564022be9e89aa5a6b0b98d88fb7976583cb2b4d2ef",
|
||||
"0xaa3e7684a3a9daeb343a10566c21ed1fccb46f4ac4b80efaa8725127468b7072",
|
||||
"0x55acb0e629a6b654ba723f330770a4238cee9aa9b98fc4536a7c8bcf6050b9e0",
|
||||
"0xcf2cc1a66e1d9e2fcd8709c6e695bef0ea95e4d14523d34a544adacaef0bf786",
|
||||
"0x6d955c9a59acd3c90593b8eb22dcd614a89ec947d554a0fc8323e817cea7b332",
|
||||
"0xe29b3ce7a0e8325135a33a1127d1db2f17637090712a0b440bcc3a3bd6301186",
|
||||
"0x47187e16fd16d67eb94e48e2f35eb520191ce412b95c1d18443487887700c516",
|
||||
"0xe2ea962ec229af7a26687783a7ba8f65490d9aed8f34bdf7aeb978c901f67c1f",
|
||||
"0xcbbc65451fd646ce67f78593806e3b66379d1a3aed301e6e67df9e3ecfd3cdea",
|
||||
"0xedc8308273c7ec9b50c8c328c62cda10e4e8505e3f67d134d0961d0fda239747",
|
||||
"0x57d5dda883a2dc7ef9b36453edcf481d97c06113d7a060131dd39133ded06e6a",
|
||||
"0x9392ffa1001ca3a85455471b660ee9d89c8d6d421fb4b00d7ef1eaef22747009",
|
||||
"0x0751d3a58d8bfce5febe6980c821c92f9bf5beb8685358375640f751fc5c8369",
|
||||
"0x6ad5fcb53f602b55dc728c7850f628ed5c500b65c6b0d22c077fc4df980d9306",
|
||||
"0xb9f2d92291fede8a3def3f527a8449f6e330d587df1ec3daedc1f42cdcbd6af2",
|
||||
"0x85eef96182742e4090221c1ac4433c106467e48f8c46ead864e6150d7d50946d",
|
||||
"0x6e800d685f7f68839978c124f300aedb6c34dd7ccd7b2dcd3144223d0e3db527",
|
||||
"0x9395edff6ff47843cda1e5cee061f449dcb7b5a0ca07daf9788079aa7c5b2ca3",
|
||||
"0xa2995f2cd9a79024f92ecfaac2cbb17a9325b3f54480bf2ae5f3d171132780f6",
|
||||
"0xef907147aaa023015d9b8f3e7414dd4b84e551af0d9f19fb918ad5f632096657",
|
||||
"0xa44d76467ee5fd7acc90c13bb12740b3fa8a0096ad0be0e3619841e67323c5ba",
|
||||
"0xaa574a790a0a50cdac6be3819be64c67427f5a891a0029333da60a01680d83f3",
|
||||
"0x531d9c8a5d68299fd55cfe498922d54af8b119500f7e6bc0c1b66b45234dab1d",
|
||||
"0x45cc89de803b6eea973d45c26b4b4287d322dae61163ecebdd3db92f8a40be52",
|
||||
"0xb305c50ca54418553d0a08c2a01908f3d413ee3eafb55eeb4cfe32aaad32597c",
|
||||
"0x5767e979f2322c81537baf5d300d24e736373eb399c0e7ae989fc0f177c40bcd",
|
||||
"0xe3646fedcf2aa89d6ab6a6a225cbfcf539317e4c59be2655b46f0d89142d9b18",
|
||||
"0x9edc1e15d3b2e5eb5f0b60f15e3b39b0be95ddf0bb6e4d18f4c52322b66c7867",
|
||||
"0x5bf071715890e9f227fc66c705e782add56e39eadd30dc982066fc067ac64fcd",
|
||||
"0xddb572bdf8c2ff6ce8a0d9b6b2c95cbb33dfa9b96bde4b74812ac016a93770e2",
|
||||
"0xf0687ab1fb94e49d1e113b1fb0127548d60ca1dcf341a1952d16dec090aa2736",
|
||||
"0x94308074a4ed0dda1ebaf569b6cd5b4b6f7e77bbc41c737c78462a1ab330e3c1",
|
||||
"0xa7141bddbfa78144aae11810acf034e48bffc3368c862d4f750112899150936d",
|
||||
"0x1560476607eb8c091ffbc0ec21cb3091c3385f9c83f8d27c4a301ac200a92820",
|
||||
"0x8c0b77737383dde0abf21d1350f0d2c285344720c314c564717ffa034acb1739",
|
||||
"0x2782b37efd53e9a34ed2742be32de2480de342a384d81bdf3359d3686a3b504f",
|
||||
"0x6e9848f3a434e019bc209a02ec769dc63e084b9c0f00472c218589dd3c256017",
|
||||
"0x721d8f1bc957b825d3abe06a6ad9d8bba2e03b915aa779ac42fd9e5bc247411a",
|
||||
"0xb937b6dbba5291fd35427afb0126ffd47962a07c3bbd6c77e4b80f6bf751c684",
|
||||
"0xa5461d8dd8d05bf13875c6b2b62c82d371163d2f8ca80c2c0ee4d94061355a7b",
|
||||
"0x58901227df5457e57c74db16ed72b9b6f9303de046e7adf6fc269db7ee9e0a28",
|
||||
"0x33cb303cd28fa770e6c9f067831cb1829a8ccce845ac6bdce7d3da5d4ba8f3d1",
|
||||
"0x3ea819ffcb3839d7a16ce09958849118a801152ecedc92de0ae5154f6c8a5d1f",
|
||||
"0x001ed88b63827a6c71d7214b42551990e3f313720d982ea5f1049ede4f9d228a",
|
||||
"0x2e346b0acbeeeb88e08ca6af0f2bcc3669e093475d8c224f23a45d4e2fca462c",
|
||||
"0xb4ed38878080e2128b706ca1ac4c92c0def02a8ec094d07312068c10f6b144ca",
|
||||
"0xd0d3c577cf73421791431a6f00452f33fd06f771de9ae2caa32ef2c93bd03951",
|
||||
"0xb3dc9827308478b197b3995e39aa930d40df8cb98fcb2958c6ff8ece2bbd4c16",
|
||||
"0x44547163a565de79110c1e42b81151a6e304df14953e648742558efa6f63672f",
|
||||
"0x487a072363419adfe51ce0b8be352c0f497e5720617e9a237500293459cb7bc0",
|
||||
"0xe7e9d6bbc5de3d62822c92cec484926d935038fff8be29ff3743008499000d9f",
|
||||
"0xe151cd789208eeaa791f146f7e7efd46c17e2f8aaf061ba5bdbd7357a32cea39",
|
||||
"0xf5e2de235cd7ecbc34828c244da80de6c9c452c253e6c876d9843bf5bc665daf",
|
||||
"0xd0bdde209238ddc6ccd1e06e6e69c2c16b38ebac8b9f3202d46bd6bebacdd893",
|
||||
"0x5c3cab37f5d83ad8fe9349ba88ead08f36e71f149f10642c819ae53b26ccb0a6",
|
||||
"0x1d069657a6a467ecb3a781a3d72a8b701faf497e1098fbb9c04ae29820fa4e75",
|
||||
"0x8fa114b013195af63e697432f3be7017ce8fd6e7ec26f23f832b003e82f17ce0",
|
||||
"0x2664fa9d45f83ddb5c8a758c6fa3201abe7ea14571c886815585c543f245b301",
|
||||
"0xd6c3528e946a4461efa56df07020008870ed64fde08cd72e7f8be581207f0d1a",
|
||||
"0xdc4c0f579f3e44278905dbc69610f7d1025e068f75e5475400d96c97297fe5a3",
|
||||
"0x06124cac7f9a1c10d48216905db968c9580b3744ff89b37b9b49e7308b04da8a",
|
||||
"0x5c0c6c98bce9c64b7b62d62ecf02f435ce54b76c58883da177611774c79d5fba",
|
||||
"0x424553682070092aa2ab3e454c66dac9d6bf6baae6379d91405a47fa48a3f200",
|
||||
"0x3d09aa437ff840909ec6024c1e407ee7b5622561e4991b76968c146ae1c4976b",
|
||||
"0x3ef50c81169af169c100f58f3afcb8e2f926d957b2adbaca8787be5d4e8d7233",
|
||||
"0x8783eaeb56ca2d7fec84e0e272b77271fdfd6c14452a2e1dd83de770c5d99a1a",
|
||||
"0x861024460895378ba100c5d0c05e62bb6cac8b21ae529ab5cab39eb6c6cabd90",
|
||||
"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"
|
||||
]
|
||||
},
|
||||
"accounts": {
|
||||
|
@ -33,7 +33,6 @@
|
||||
"eip160Transition":"0x7fffffffffffff",
|
||||
"eip161abcTransition":"0x7fffffffffffff",
|
||||
"eip161dTransition":"0x7fffffffffffff",
|
||||
"eip86Transition":"0x7fffffffffffff",
|
||||
"eip98Transition":"0x7fffffffffffff",
|
||||
"eip140Transition":"0x7fffffffffffff",
|
||||
"eip155Transition":"0x7fffffffffffff",
|
||||
|
@ -33,7 +33,6 @@
|
||||
"eip160Transition":"0x7fffffffffffff",
|
||||
"eip161abcTransition":"0x7fffffffffffff",
|
||||
"eip161dTransition":"0x7fffffffffffff",
|
||||
"eip86Transition":"0x7fffffffffffff",
|
||||
"eip98Transition":"0x7fffffffffffff",
|
||||
"eip140Transition":"0x2a",
|
||||
"eip155Transition":"0x2a",
|
||||
|
@ -31,8 +31,7 @@
|
||||
"eip161abcTransition": "0x7fffffffffffffff",
|
||||
"eip161dTransition": "0x7fffffffffffffff",
|
||||
"eip155Transition": 1915000,
|
||||
"eip98Transition": "0x7fffffffffffff",
|
||||
"eip86Transition": "0x7fffffffffffff"
|
||||
"eip98Transition": "0x7fffffffffffff"
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
|
@ -33,7 +33,6 @@
|
||||
"eip160Transition":"0x21e88e",
|
||||
"eip161abcTransition":"0x21e88e",
|
||||
"eip161dTransition":"0x21e88e",
|
||||
"eip86Transition":"0x7fffffffffffff",
|
||||
"eip98Transition":"0x7fffffffffffff",
|
||||
"eip140Transition":"0x21e88e",
|
||||
"eip155Transition":"0x21e88e",
|
||||
|
@ -23,7 +23,6 @@
|
||||
"eip161abcTransition": "0x7fffffffffffffff",
|
||||
"eip161dTransition": "0x7fffffffffffffff",
|
||||
"eip98Transition": "0x7fffffffffffff",
|
||||
"eip86Transition": "0x7fffffffffffff",
|
||||
"eip155Transition": "0x7fffffffffffffff"
|
||||
},
|
||||
"genesis": {
|
||||
|
122
ethcore/res/ethereum/poacore.json
Normal file
122
ethcore/res/ethereum/poacore.json
Normal file
File diff suppressed because one or more lines are too long
130
ethcore/res/ethereum/poasokol.json
Normal file
130
ethcore/res/ethereum/poasokol.json
Normal file
File diff suppressed because one or more lines are too long
@ -9,9 +9,11 @@
|
||||
"durationLimit": "0x0d",
|
||||
"blockReward": "0x4563918244F40000",
|
||||
"homesteadTransition": 0,
|
||||
"eip649Reward": "0x29A2241AF62C0000",
|
||||
"eip100bTransition": 1700000,
|
||||
"eip649Transition": 1700000
|
||||
"eip649Transition": 1700000,
|
||||
"eip649Reward": "0x29A2241AF62C0000",
|
||||
"eip1234Transition": 4230000,
|
||||
"eip1234Reward": "0x1BC16D674EC80000"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -22,8 +24,8 @@
|
||||
"maximumExtraDataSize": "0x20",
|
||||
"minGasLimit": "0x1388",
|
||||
"networkID" : "0x3",
|
||||
"forkBlock": 3383558,
|
||||
"forkCanonHash": "0x6b4b80d65951375a70bc1ecf9a270d152dd355454d57869abbae2e42c213e0f3",
|
||||
"forkBlock": "0x40E80F",
|
||||
"forkCanonHash": "0x3e12d5c0f8d63fbc5831cc7f7273bd824fa4d0a9a4102d65d99a7ea5604abc00",
|
||||
"maxCodeSize": 24576,
|
||||
"maxCodeSizeTransition": 10,
|
||||
"eip150Transition": 0,
|
||||
@ -32,11 +34,14 @@
|
||||
"eip161dTransition": 10,
|
||||
"eip155Transition": 10,
|
||||
"eip98Transition": "0x7fffffffffffff",
|
||||
"eip86Transition": "0x7fffffffffffff",
|
||||
"eip140Transition": 1700000,
|
||||
"eip211Transition": 1700000,
|
||||
"eip214Transition": 1700000,
|
||||
"eip658Transition": 1700000
|
||||
"eip658Transition": 1700000,
|
||||
"eip145Transition": 4230000,
|
||||
"eip1014Transition": 4230000,
|
||||
"eip1052Transition": 4230000,
|
||||
"eip1283Transition": 4230000
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
@ -52,9 +57,9 @@
|
||||
"extraData": "0x3535353535353535353535353535353535353535353535353535353535353535",
|
||||
"gasLimit": "0x1000000"
|
||||
},
|
||||
"hardcodedSync": {
|
||||
"header": "f90214a04d45aaeb1f0e00495b99f5fdc46c2c1e6b0fd48c693678de72afc1cb6f47a086a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794120c78af68df5957e776554d138a6b75f2c34b6ca0f2746b213421be4ec9cab40fa41aabfb4a3e8acccb6506d6cea4863774374dafa0225a348dfb2ef00db09da39b1a11b31741b6d14fd4456cdf4c2528961f398b74a09528322c1ce98449eed355ddabe0192fac920910a0d88965444b9efc1ac218eab901008000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000040000000000000000000000200000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000100000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000100000000000000000400000000000000000000000000000000000000000000000000000000000000000000008426e4d4518334e0018389545c8306529d845b284db896d583010a068650617269747986312e32362e32826c69a066f990a9ad374c2cb0017e96d3776e6c787f679d77c9079fe2b046279453d0f88851bec8da753bda19",
|
||||
"totalDifficulty": "8635599198809021",
|
||||
"hardcodedSync":{
|
||||
"header": "f90217a00f0e017311206b97b47403eba05a16ada760a691a36f844ab8bc9082a4efedc9a067baeee20ae4f4216ab4b0c41198efd376aca23e44b1d6575c5949955547b72a946a9ecfa04e99726ec105517ac7ae1aba550bea6ca0e64d4fe9bee34d98e127f7f94f17535582d5bc6eeb6219f323b046b9a98c72b5a02d33ce5daab0436707c6d958dcf0bcd311ec7a72d7b33c20784178d5d95bc6e9a0a5b9cd4802fafaa9381ec0aa745cdb7ac953675e9df89474e5fe14fee134cf87b90100000008018000100000000000800000010000000050004000800000800014200010000001000000000001009001000000000000000000000000000000006004020600000000200001000108088002260441000020204000000000000000000280000000000200010001000000041008002000000004004c000000001000000000008000000000000800000400000201000000044001145000000000000001000a0200c04000a00010080100000020000000400002040000000000040000000040200001020000401000000800080080000400010000000200000008020020200000101000000000100400000000004400010020000200000000000001000000008453461c8683402001837a1200832c5216845bbd359199d88301080f846765746888676f312e31302e31856c696e7578a0c1da176f6642888b4369e14349ca7dc125ef7d4f5f7abad61bd7f6b95bfd46bf887d1a171a9f55dd67",
|
||||
"totalDifficulty": "12027449412394243",
|
||||
"CHTs": [
|
||||
"0x614648fc0a459451850bdfe353a932b5ff824e1b568478394f78b3ed5427e37a",
|
||||
"0x1eae561c582dbb7f4e041998e084e165d0332c915d3a6da367638a8d24f3fafc",
|
||||
@ -1747,7 +1752,367 @@
|
||||
"0x8baa0703e1a050c40f85dc850fe477881f432c951b1cc1b2b71ffb68ab7fe0d7",
|
||||
"0x14ca94dfd343548e32ef5659c043d6e28f0e577fd38da1ee12f11c08e281d775",
|
||||
"0xef25357970c76a8b72a6e52f49bc30651f711c7df70444d4667e80febc0e3b2a",
|
||||
"0x41b8b4ebd5919dad3bc609ded524b97403d88f019367f0f4f622561131644ffb"
|
||||
"0x41b8b4ebd5919dad3bc609ded524b97403d88f019367f0f4f622561131644ffb",
|
||||
"0xb29a8ad1157621d0120aedbd8dfeb4b318979bd43a5b018bf7b9ce33d85da312",
|
||||
"0x9ddf78b5d67ef40454867ed33de83a01cbd8c18fe09da3d9f991a196811dfccd",
|
||||
"0x3604121f9cfbb5cf552cf8bfc9a7958332eb97131158e4f40f4eda481e553991",
|
||||
"0xf1778830f694720a6f990f9d476b0f365e8a74880253b55ee16f5cbd6c8082a4",
|
||||
"0x89831626d154fbe84a4c62c3e2638cd00e42b3844c7c7b98cfad113abdbc5347",
|
||||
"0x650573f5ef274b2aeb40642e25fbd661cb0eff66245d7cc8f6fb9e9daa80fc12",
|
||||
"0x479f6c652173efe94abaa850bffe1557847b26f286467013a4d72973e05e8e54",
|
||||
"0x7096619d5716c34592ac2d9907ac28a74c6f6b1ebb1962a0217df82bf3e714d4",
|
||||
"0xb7c7edbd8ae7eed58e973dc0750adfd04042ed56baabf372b111fce3e4b4469a",
|
||||
"0x25529b597bd15317e55767b3fbfecad0657aaeda99f098186b41b70811f7af2a",
|
||||
"0xd790747b09f925fd155b7bbdb5ccd89d873277163e4fe7054bbf71c0b26b8072",
|
||||
"0x3aa0b221d1c4743a06692f645f38a8128d55f1c07cfa6e9711b0d2e0f2e0e738",
|
||||
"0x26fb5017218cbe4250d2ceae751e99b9a34d7befa162dc248ac008c5d1221e71",
|
||||
"0x0e4ada59854027601f8f81fbdceb95228db667eb65fed97cefbb35dba21d3b52",
|
||||
"0xd3be75ae2da3e271dd85cd8226d789aa12d108a4b0d2681462f6539637572e50",
|
||||
"0x6f041891c8219b508138f67c95a1765d08c5ec06b9ce585f52f837806fce0609",
|
||||
"0x9e106515d0e80b41397b2e8e98adbb7333e76265917339a62063a07d9a7ed311",
|
||||
"0x25f47483ecc5ec32f94b3dbcb4d42a4cdbf5c279e93567e14afc742a4619d3e0",
|
||||
"0x5d81afc54f6b68bd820dcc629ff7e9d8397da56ffedef9addab0eec620de0757",
|
||||
"0x36e192130485f248925d4b0d2fd98745a76099eb13f53093621d216d0aff0d6c",
|
||||
"0xb906e5e33b63f6cc355c13b8461a260ee25376ee96909fad2c6ac121ad831496",
|
||||
"0xd68e7e0d136e30f67ccb7c21e4dc43b0ad5536584e4b77c9da8d903a04e9d212",
|
||||
"0x5aa7847a4bddda7fbffa62325da920a21a11524ac1b691bc3b55e4d1790f24bc",
|
||||
"0x331f95f062ed1d38dd02b5ab6a95dd238ef97c5ee9777c938697340c902b4b5d",
|
||||
"0x8c6a580c8b07567f747bf20946023c3b581c51075cce5cd5d47b0d81d8922135",
|
||||
"0x8b89483810a49626f90846a0b49ad3e2172657dfa3003d58fa2a43d12c8f4090",
|
||||
"0x944f9a5754800a33d903c8a464d602fc9da6af8ff3990c3eb669ac9cd17891f9",
|
||||
"0xc75c82a2c1ecd875d16f343a58835d756740902c246d3b1deae97e49aa19f98b",
|
||||
"0x1d2e0f2f87ff2b08514b18855c343966d42e0f1a048ddd3d316dca6e06292db9",
|
||||
"0xa6508507463e53b3a840dd55ed9be57c8a56e1533c9001276750bdf19796f8ea",
|
||||
"0x01eb6b636b1852e8f9066c12d4e6b7b06b90a325be4d97e08f7f560bab4796a1",
|
||||
"0x8a0d77fb41f50808ff0a46dc9f3831a2b5093f55ec2e94a3d2e92373ff3b5695",
|
||||
"0xea3383ba1d30891d1e236db2b31373541f51a9e5c4b4d017cc4960480dd20311",
|
||||
"0x01129e8d7eff516a225cc0db090e4e38362d9eb2d0571ce00f4417836de2e375",
|
||||
"0x92feaefb7f9466814a0220e536fe5ee73560507d071e059827d406329e609f87",
|
||||
"0xac149150c11b3bdc660320a0e955f154fa3137549a73951207659e2b903c145b",
|
||||
"0xcb68cdb224f9b3b0b0f3ca0056e70817146c9ebc75876dd952e6ca8ea896f2ac",
|
||||
"0x157565282a12d790452e343c9762c2124456039729f3a8f97a2cee60d85628fa",
|
||||
"0x42eadc181d59d8d8b26b37e0e9c9052e45bde72090d330bf9cf21d9d3c7d9048",
|
||||
"0x1ea0ec8879b200e259a3a2a0f2a7aa292301784fa422f7c32ed5d945183948b2",
|
||||
"0x06aeb2956be9d74ae4ff0b8a6c1874ed8ba46a186616356dc060bea1cbe5c628",
|
||||
"0x814b0382b52a155a4e35639aeb3d8c859afc4fe5d151de3b0f1bac646e40f2eb",
|
||||
"0xb30bf3e85be41a2a9e53321ee9f03c7078516c72c7e2d8e7e3134de709b61c36",
|
||||
"0x1f97f5d334b5e6ebc72f5b846f24c7911f4fd1653f89b3477ce4b8108342810f",
|
||||
"0x84c6fd181c28ad159ff18d203d14f966668468c9ef0a5d6dbd863886a7e0af1e",
|
||||
"0x4b2e6947d55ea504bf205bae9dfc0e5402efd33757eea4da00a8ed2a6a3838ae",
|
||||
"0x85f31d45128bb91cd3490b58a0a641ef77246ea9c83de30fa89b621307fd96f3",
|
||||
"0xd362f5e6f8cbb216e66eaf49e4df25e01504ac729da86c530871a34e11d302f6",
|
||||
"0xb7860983b043bc13ce5a27135eea12ffaeff71879404b18af3079b98da156bf2",
|
||||
"0xf2ff82a679b2b90cb9f4a3bb903eb7ab36ee1c47cbe40024d8d570f5e16bbf4e",
|
||||
"0x7e34a7e6673146b6bb7f78593b6093ef15b8e9fd1271b33dc5f7d17876b31871",
|
||||
"0x725c97f83b4cf213296ef353e1c8d64854ef08983fd61320088b8d9e2ab33849",
|
||||
"0x18085800d10fc7845148835d0ef0ac980a82eeafc44e12bfa296f9c38fc6e19d",
|
||||
"0xc6c3cf95310cfd0254f0f8e93a3c25bad2b17df04f9c51a25927b80d02e06b69",
|
||||
"0x822213c1b03cf68ecadc0b7572d37266207d5fe4efd5e56a924b0a1aab8a8e84",
|
||||
"0x1ff46ffd2dd880cca76244f6af1fd8bddbb4b9ec58f86639821a16f2ff08f3a8",
|
||||
"0xe9d00df19d716dc859922f2e6c907263191c8e531498ea557869ea1115317c95",
|
||||
"0x6d3f1edebd562e9d1a236ed7a1d9104fd8f5a086cd78d35c7a65f27c269d98ca",
|
||||
"0xfea701ced5bca0d5043512700598d3eafa0b89dc02f3c157cd1d52bcf4d84d9b",
|
||||
"0x556c1cd8ff3ebc2ccd4eee9f1ad3837e346ecda961da17c0ee9cd4d084a47653",
|
||||
"0x5606be2fba065424af76c94d4156ea82f77d9872ddac7a4c2517957a169e58f9",
|
||||
"0x8d0223425b48487db1b371c966c7688435f4b9fcda75b088f0aac203d6657cb1",
|
||||
"0xfceb55d8f3048a3f2255562e0a9ee342439253abcd048fac151ef4b910048e22",
|
||||
"0x360f76e4f2ef49632e3bf8cfc3afeccff6917e98a48d3568148c3bb13f9d2d7e",
|
||||
"0xd87bbf8397204cc2af883362646b0ae95392303935ec1997ab052c194e0ef117",
|
||||
"0x9f1dad9dfecaaf117ab5277caf672b70540578e703c2024d3f23bb7cf8d6410b",
|
||||
"0x5e130ccb23b7b66dd2fbdd912d6006d2820071dafe2890f593f952028aaa19c0",
|
||||
"0xccd2f182107992fb9b002b87cdf7990cb2810b202b2ae5d6ef5e0b3bd69632e2",
|
||||
"0x4b40cd83205f8b946ca9f11fc3306872650e658e631511fd4080bc8ca749d913",
|
||||
"0x652acc59b71ca20bb65ca195d1a4b3e177f6a3985bdcd6120e1a45b7d4a0c7ca",
|
||||
"0x49a5e2580ceb329665244e489592aea27d54da8189a665d9435e037ea70c46a5",
|
||||
"0x379801356beb3a8e5fa7311792c69c7ac1f675a9c08c837f9f0e9f53c243d6a7",
|
||||
"0xfeff4543c70356b7d9767c26b228cac8452c95bc4875e92a60d7e6fc50468667",
|
||||
"0x82eb18827313399cb3b0d3c975eb9a9480c3aa5587ce72d321bedccaaab56115",
|
||||
"0xa644c582a751a6d8cbf30e59d6e770a6f441c017b486cdb23e6b9c48c614967d",
|
||||
"0x75e6f4d4185515a3c58dea60b55d5e50af053bb261db2d3de00f812a4072ee2c",
|
||||
"0x9018506876afe91cd2cded037f41c5ee8503fede2a59c47dfe7ea1b36c460f73",
|
||||
"0x0b8bc06bf211f715291846c6c34b805b6aee91ef4e8c63cf3d15ec79b44ddae8",
|
||||
"0x150e43fee00d798b8611d4e03838072d8b9c8ee3771e840ee2c161a541d6b643",
|
||||
"0xe98c938110bd4227c660a9bdccba3b5ce5b8414d909514502e8f354f96abce69",
|
||||
"0x0fdc3bd666d74a99e623f6d4957bcbfb17395bbdacb52b18ecf7aa5d2e4ad2ce",
|
||||
"0x2c72d738e803c0522b5f424731ad6327548ef08ded4caf4ae0466b2cf171ac4b",
|
||||
"0xa7709a082f8a2ed01e2e88c4a2d18930f510fe5b831d2a1bbb1a85a858f19e54",
|
||||
"0x8ccb960803f6b6e87515ec20a36734128da0dd6e65845013d89996070d3cbc69",
|
||||
"0x4ab2e49286c8505f32ca54314d1b5c3b2952578d191c69d1cc7ba78a000a01d4",
|
||||
"0x6bb792b52949c952f20b9d11274c8a05edb44c4070d949bdfddcb0eef2464454",
|
||||
"0xf61eccaeddac91487b2f5d7b3ec57d1ccbdd0e1307d2f624319fff525149941f",
|
||||
"0x2dcf01b0d9ce31c13c20959618f2e5e0c7f8c48521f00c12c99d28bfcf202f57",
|
||||
"0xb1e83745e6013706904b7322350c8b453aaaba0a61ba89f35eef8f19759ceeb4",
|
||||
"0x8a2cd4944bee70696aa216b453774f4d915dee4bb78c8f7ff55410cddec318fe",
|
||||
"0x49a78ff97bd4938cd030df23e5ff4d84ace59ef3fdc0099941d8ad7f82235894",
|
||||
"0x61e2096919419c8856a5473f135f4f9febb102f80eecc90ad60baaed77a99d29",
|
||||
"0xb95709562a26564e57cafa00d0969305ffdd0aea7e523ba90957a6cbad6ceb70",
|
||||
"0xb7a6438f176aed77a9c6470e28ab8cf19dad8f77dd3313cfbbbc9276761f454b",
|
||||
"0xc85a1c37b5a4e1e8ae67df31b369f0b44cdcf66418b42206e5b4a738a0a0bae7",
|
||||
"0xf034b0d125eb1bd1bbde1fe413aef80fdc136339eed062b97cb9da2f4bc94ba5",
|
||||
"0xcddbaba3e9e1680a2d1586a1e9e2268afb51b4894f2b41fb2eac5f667b6cb655",
|
||||
"0x971b2fbd25a97bc710c30b6b98efc90428a7e423c09fe772622e7ea37d18e49c",
|
||||
"0x8571bcf05c836a59a5d3216634ed1f691edb7bcddc7b5412bc513ae9e1fc0423",
|
||||
"0x0543d8abe5e1bd541a5bc994b0c7ea5a556575d2e9302d1dc36348ebb7ab9e82",
|
||||
"0xebd8f9095619980043f234bf4f7682534ae6a15b4584e9d1ae524138471467c3",
|
||||
"0xd0699a768c873ca5bd615ab5b0fd9c7c6c649c4245b58cb622210ac2bfcf3111",
|
||||
"0x35bd5a50b11033878751d985459657bd4c0206584cd1def98a355d7ffb0539f4",
|
||||
"0xd476d2b8b62b720520ba0990137629f83db9c6896f1e788fa5bf08614af1f2bb",
|
||||
"0x2a8034765c582c07580c0da45c4216bb513171d073a99cbca2fa2adc0c05dbf8",
|
||||
"0x084b45a575706daccfbbbcc321a9546b0c911861f2639d81f210b77680f60fb7",
|
||||
"0x499bfc54ba17718aa8f74ceb412dd9b6b6c7d1cbde4d8ad2385a5d5d77e98915",
|
||||
"0x8638684b06607afb53385f477f0f295453f14e36161da6dc7728336475303a9d",
|
||||
"0xa686ad8ccc3507627712d203f7ff3be65c289da67269388d0ad8949ad3a5a589",
|
||||
"0x6d262ff8babed3a603f400501cd77344585fff92e5bab5f5848873042ab87cb0",
|
||||
"0xb5755234055b3534fceeafcc84d0d77dac220d3466e1dbbbe7d7d44c345e1eec",
|
||||
"0x92a54b989a1aafd36f979ff0f1fc73f9b1508628f054430234f4460cd9f3959d",
|
||||
"0x1a48d9bb57e9a70b03c066c97ff9520c177b8361f2b3c343ac71fd8cbdbadba5",
|
||||
"0xc9e103919e8b6827a1fd57a3e99155a24810f524fb69a7e3fbf486707b2da690",
|
||||
"0x22a5ba2899ce696fe691a2c545b98ddecb7c0a844cff2375e50e0a0f0f9cf9b3",
|
||||
"0x154890ebebe7f014aa88f8da52c9713e2b0cc8b9b6c7d29b354afa000c2eb429",
|
||||
"0xf9a72e3ce36943a442d0dbc7a869a6344003d6a7ee4d344c1899ab8b96746a6b",
|
||||
"0x270fe45a526aa3bcc8e4a5be075610ae9b15d6fe48b04c6ff0c82a1c7f56e0d8",
|
||||
"0x9eacbdd695faa85bdbff10bcefcd5edfcc489c3380cb1c73ab5ca6cba2492995",
|
||||
"0xca15124d292e0465c7e50276cfd374c82391bb668d68a3b19c67fbb9e68b0bba",
|
||||
"0x9a8cfd3f1b8ad178c982feed1fc306dc996da3d928e99a6f8ad240e55f52cc3e",
|
||||
"0xc173b14778977c5d6dcb1079023c493406911c6d6791ad08104f847323aff7cf",
|
||||
"0x82b3e9b9a407ff0596aa7eabdeba10dded85fbf3258d12949ed4f46484e0f649",
|
||||
"0xb8a009c28a2328b7c95531bc64e072388d797130652ea0a84159c801af562a5f",
|
||||
"0x80e45ff8b60d28dbb45530b7b56e049e605d28087df7133766de0e151dfbd01c",
|
||||
"0x7667e9cd22c5427e6f37f215b1d9cd90b2659d5db0bb499daa382e09fcfd58e3",
|
||||
"0x825014f354bee6aa4cf5283f86e8293c0ea6faf07862abe2cfa12740a0d846d3",
|
||||
"0xbe9116073311dc303fa29f7a226ff79fd39ec2ffbd2d2270652b972a701aef54",
|
||||
"0xb3fd19eb6b0163156a350156b15e660853f68a903ea6ed758bf80b2fbc5a655b",
|
||||
"0x3c5a408909bf485e8c3d8e683d8ae4e7b7149d1f01874807428a3f88e1293d4f",
|
||||
"0xc759f51aceddb90e6e4273fb9439908592dea649f5202f530d15d455c5c8c7c8",
|
||||
"0x1fc97f79d1b1d72da309bf2027ae193f0594ecb77c07a472421baadda577a24c",
|
||||
"0x09c4fd284e5c0672ad031629e58fb2776d1e772c6041c91433f287304dfdcd1a",
|
||||
"0x8c6b40f8700a0638ca5b7bb003c2de6b54e731881a072988cb78ba89557db1d6",
|
||||
"0xcbc701507f4f970d8dbf15306d6ac5bdd46b6f58bfd2dd07db4ee01c65aab5f7",
|
||||
"0x6b911e52f43696cab429c0e511fc40011846af92a2631f4d3f2cd040567f021f",
|
||||
"0x4fa5373f6eeacba61818052da8a9787c4ed86be0bffe0672c0aea792cc3d2d49",
|
||||
"0x518ceeb36cf1a406b89040ab0c60e380068f5f6571d042d3bd9a9d7af1b12204",
|
||||
"0x82039214db7d3beae631682e9249b06f98e16153f864c2026a6edcb0727a6532",
|
||||
"0x9a9e534af83084007e54dadbce2a0224008a8c42356c2ea650606e8e72d2ad8d",
|
||||
"0xc4dc0b662ac8d4d987b8c2c65cd27fb8992f65d598bbc25f017c45b7032451f9",
|
||||
"0xa921f124b5275f07b2c064d477d5779963096632f03c54ac9c87917bc4aa6e52",
|
||||
"0xb4fe786c84a19c8db63117c421ce53244436d0c04384c62d508a88589f4e5c83",
|
||||
"0xd57ea382802130e3ee8e7671be2b40a1392ebc6528e2e10d9d51f2899ac7ea54",
|
||||
"0x224523fcd11abd078840803bbde2c3d1d359a0c2cfdd6f9110a93ac4d3c49845",
|
||||
"0x5da21f79c0f1030e2a5dbfa283becced75e7ff223ef14a6cb5527434503ac71a",
|
||||
"0x3e315746e89fd3e662f4dfe28245457c3b8a4ea6d9450b93639424a6d8ef7d41",
|
||||
"0xe142bd09a6967021c4c5a5c7491b0df3b1bcf13564ac934a2668e1b2252e4723",
|
||||
"0x2e9ab88b366cba155d1f6093e4edbbafd80032b07a192a35942aeea1bf0f1074",
|
||||
"0xbcbd1b446853135abae9f330d63a06119a93fb53b63c621941f5a74324c384a1",
|
||||
"0x7816de8933a433aa2719c99db24e692e6ac6551416b08f803302c7751fcfa3ee",
|
||||
"0x52c53032dd84842dff6580013ab1edca7c251598ba5fc8b903c40e3d9e537095",
|
||||
"0x771222b46cdcbeba729436ef39f81732aaf4893da720c1e7b59ebb3fd38ab9d6",
|
||||
"0xfc440de1896e1b2848f2cc5c7d62c0a6b0019008de8aab41df5395586d340d4c",
|
||||
"0x0df9b803307465e54cc77ee60dd6988e3d713d496ac0209509c5312ad0f19888",
|
||||
"0x88179429086844e69122c70b6af8b689abea11e13ba0809743532663e3047c3e",
|
||||
"0x503898d86c4038eb76124e18459e0d57ec25b177fc79bb87eeccce3fa75f0037",
|
||||
"0xf46efd490382e4e4a3ac0e10926b46ec56e833769acfe3879acffb13030cfe9d",
|
||||
"0x6efde5293a9d22e688165f2a51bb83e3b53584f9ef5bacc0bd1d99f5c7df18d4",
|
||||
"0xc03dc313d9be55674000d061851c139f4c57c6fb46106b98c3442832a51c5f3a",
|
||||
"0x8ec2accb7c89019d0fe2a31ddada0b8251ebe88a439de9d68be73c0994a6523a",
|
||||
"0x36ec73d7e8c0181f6335c668ad7713f8eed607e0c302b43413f904b26160bdc1",
|
||||
"0xa53e90d88a751a78397adc6d2fb4f93ad2b38f0ebd00b32932c4b2a39a276d9f",
|
||||
"0xea2a25111ca37a53c8fade1ef65097f0cb85e00881b1ff201d36c9151a8e1a0f",
|
||||
"0x8c1a24ac75821a4b0570c22b682c6030c678244b059ffd4b21e4d3cd05afb585",
|
||||
"0xd230d46b14f9586f7b1947add191a69ed381cb6fdaa9b28c28869da8c6724dc6",
|
||||
"0x4e8c717de6c94b4be274f052d9df627c945afe18df35c58a90a035759dce6b48",
|
||||
"0xdefefe94ca6d93b78ef9f92911eec4c2ae0c10148691755f1624f86445a3b2b2",
|
||||
"0xfa6c031ec69c7dac9f9b6524054806e2fa524c3200fdeac030d3bf7029ab776b",
|
||||
"0x9204683278cad559a3f9ed2ec1f6539f34efb17957830d0aaa92b73cd0994732",
|
||||
"0x2bb26a0cc5eb7424033e8bf552c7964573a0954e5b6aae32a51d95d951fc044b",
|
||||
"0xf6e3827687af53fc532ba163d7ebd5ce18ffa6384157982b6dfdb1f4be82faf5",
|
||||
"0x627bda246bf499f4498e8c512c8f601e36a1dcd778f21a598736f83b5b33fbd8",
|
||||
"0x5816773273e4ef45fbacbe920dc3420602d8134fffe302459891cd6e65627f6f",
|
||||
"0x7cd637fa8a5bb32dfd7c076c34e0e536d7c6710f1888f5ec18d64191a9930744",
|
||||
"0xfe016a6e9ffd59237b349a817ba8c36f7775fef6513c4d430fbfc20ce72fcb1d",
|
||||
"0x7c466b30cf23cb7115a3855d9d9c537c29f380ecfd7aaa0a6e59d9680bc43971",
|
||||
"0xc49551e5eb138d28f5557ea8e8a8bbc7c058084ba0edf8f6bf64471928ecde43",
|
||||
"0x7366cd68072f52c5644dc9fbe2e72339705dddd2b03690dd748265723944e754",
|
||||
"0xbfb7c3bed071283cc18cca4192e2bdc1f97aee9b7185d493a29f20ed4d52ae3d",
|
||||
"0x40c9fbfde126c8c92cf6d15a18be4b5a4da39ff60ce45cf5e9a2c1782244947a",
|
||||
"0x1358333dd1b82e7c805dced5dcc2edd5d5784fe8104b64eabc598096c26d05ed",
|
||||
"0x0a9777f7711b6d9f6cc6ad4a78b716199b57f026d1f30f04ded5d2cd8286322c",
|
||||
"0x7a848ef083a03e4112c75bef258633779cc495df4ac5529e12c8eadc484baad7",
|
||||
"0x17025c4c255f509163d11df3cac35c1de823e5ec71cfd66693393882d81fddb8",
|
||||
"0xed0a2fe0dfe85c7d606d0d1b355518a48220e91202ec1c1178c8b37c86e1c9cb",
|
||||
"0x4674e5e97dc0c615b03c34c702ceb07aec48cd7e8edc953a188d194a8cab35c1",
|
||||
"0xa004c31b7a6f6511d7eeda4c400c5ede847ce2ea4339641b6c419f688cc4e574",
|
||||
"0x1bb6c124e94df05e091f6aea45e7658351fd21318e91105274a15be4f7a7a632",
|
||||
"0xc365b8bab2d6b902508d075195a1e23b04c97e40217c4ffa49fe16bb13e5b575",
|
||||
"0x93c1383e2ab52ded5fc86e1b6f6e292c0d0977e8756e1fcbf87b099682060e25",
|
||||
"0x2921b874e3855d9afca966d5088e9b1cfe59f37db54bf0c1e8bc5c5a97e7ef6c",
|
||||
"0xfee916dad70495cb45c6ac632241a73869f0f553bf7172cc4e63fa382a5e1077",
|
||||
"0xc63d63b401941d11edf755d7b6564b4fcba1f84ed99cd08f1580faf2c224478c",
|
||||
"0x8069f00ca36baba06b310e28f6873e78b3ded25b456d95dad7eef4c517e7d096",
|
||||
"0x48dc0968af32e91a8a3f252bc0082d7c22f8dd9797e4fa774d5b5365386a4602",
|
||||
"0x861ffb24def147c4577aaa332aa2b5d3165542c4fd1e1882a9050e5de10f1f57",
|
||||
"0x9fdfb7305249e7a38068f8099b74c5584a2f2df3f0514371f20042a6c0d2c85e",
|
||||
"0x90212f15c5d6b686810e1895a139bbc26141181c3c472ee28ef9904553a2faed",
|
||||
"0xdf967dfde0b63153142628dae7522307afb35b24146d9fc1d35874914244eec8",
|
||||
"0xfb17a9d9e9a5ab6d742f55c0e8d80c5e5d722e9411e84bc47b1d2fe5fc33dd71",
|
||||
"0x56b2c30b802088f9ebf0918c7ce44b50a96a0eac98f89e1711f53452006259c2",
|
||||
"0x4c38b33bd4089a48a65369955540219b44af520000b8f8c346bdc96d47dc2479",
|
||||
"0x7d3487d3823204a94e557b7a942d7c657c1b49d9f40f2d739a9099d4438695b3",
|
||||
"0x2f82f94eb74aa2c0fb91bdb38ba0b416ce7e033c7e2a74aea113d201b225e24d",
|
||||
"0xce8ac4b2f0f74601280bc3df0f5955d033e5c511372d812b36dffbca4b2e4736",
|
||||
"0xb6ea6c89e91ecca1fbd723188a77370e9d23c3df8aac282cbcbe000b13d31b57",
|
||||
"0xb8b8b7cb900482562227a0a1256ddbe822cdcf134a196e29b1aa6fd92423a4ed",
|
||||
"0x0f47ab9f4985c3175e0a30a237d4f7c42db4a58f95344a86a818e459296610fe",
|
||||
"0xc26a55a23eb390fc83fbdc9f07ee3ce09e8a2b28bc09386323ffc0844e13be24",
|
||||
"0x1d5e97a7fdf5f34192e9b6dd255c41b63e24e1b4ef4ea43ae510fd1f50abb022",
|
||||
"0x58b6120c4f0a1004e51703e77decb1c85bdd40bc83654d3f8ce5f7e3b4b6ca25",
|
||||
"0xa2f4b27f5641d9294ee0411bcabc574f94b294ed8c50c9ae0c3d58caea7d6ba9",
|
||||
"0xc4d6d3a8b4debec7ec7f3e2a6e1c64de46ec1187ed6e87fa2d87412c9874a3a6",
|
||||
"0xfb59d9b66471893988d0fed17898fe2b7873d85aed217c20b6f438ed70fc340b",
|
||||
"0x850df664737f288ae16d701878ad04f399b367fccaa2ddbf975d77868bea7cf5",
|
||||
"0x4dfe47362c005896f82ac2d02a12ee9418693cd2f5d1bcfdc321980897171993",
|
||||
"0xb652952de1bf9e1174e5f6a37b069b437792672a37a9e0159c4f36b6e64306b4",
|
||||
"0xb72dd6cb5df1b00dbbd84e097e2da79af2ce60559697ab4c93b0a8b85b2ee406",
|
||||
"0xb96fd4a94ac30c10f757691f7f06f25a4900fe424f4eb7ccf322e2f95249b914",
|
||||
"0x99fd442599036f161ccef1ae8088c5ef694c1819f5b76d9d2fa8f979935f69f8",
|
||||
"0x3e53574f6ae31a45ef928f9c37bea6c61e6d728a5ade9851567d3167f5ca3314",
|
||||
"0xd7e3d08c5b71a7ad8338e8b51ec54cb11ad4d643d129a371af07376f8c47c1d4",
|
||||
"0x1033c8aed4ec46377f75cc9a6b3297e1da0a7d1e74df20bae9fdf6d037afdc28",
|
||||
"0x924d621544f3301f9e212fbb95872fce9eb4a4172a11693674de733bfc2b0018",
|
||||
"0x7f61884149ea4def1444a70c022da1c23f31ecc51bb175905b492236a57c7fde",
|
||||
"0x40c50785bc0665ab4eb3cec95405e17510c571570a5859ead804530dbcbd1387",
|
||||
"0xf806491cf778f4796c0f73428e6eaf237da8488af99e9b61d72c56fa03e7051c",
|
||||
"0x7a9670842dcb12c66f11e357a84849cee227ea5a7351e7c6c9370e9ef2560129",
|
||||
"0x1c974da4e1073157c10deac8b256c8ced77a030e0500b2b8a90b6ca1d32ab4fa",
|
||||
"0x97ebcc81ba9c1e04865ee4617daa967dec39f65501be21fbbe929db869d57dd8",
|
||||
"0xa36e4506065d8b9c662697b18ffe50ed2f6ccfe6d07a065bdad048778cc53668",
|
||||
"0xb9d5566eb0d40bbb03114d333d1d1dc85b0e780ec63229f3b93b2c84af5f9509",
|
||||
"0xcd16693573724880c3c83834d516be65c35a861b76b43878e28aa7fcbc961361",
|
||||
"0x4f60ecd7811acc087fc4557fdfaa1a0b522fe30da1cbae5e7740eec3cff04c00",
|
||||
"0x9e58573b152bf5008e0ea3fc0d64573211916521a62fb08ba0f1b44c5da12e7d",
|
||||
"0x2c6693cfd7e5bf9a3d8cef9e186b3da25d07af983564ced6238f9191b020f105",
|
||||
"0x8cc6149caeafef85ec7b2456f33530459c52b30a5365a2a0022b1c308357f7b4",
|
||||
"0x6f66863bd9909f687523128569cd0894c4cf41e2eddd5cd9c20d30c446b1711b",
|
||||
"0x402317752053e7b6d7e2d5512d6397112d80ace0873f5f9d32c023a402ec03b3",
|
||||
"0x2fcd50a79495057908bd34875e3531e6298488f0d06d043fb6fb0b140895d379",
|
||||
"0x533ba9669dcee2c6e35713c7eca3bca168a326a36b0e39fcde76cbd35ab3d99d",
|
||||
"0xdc2e86503e8066bc5fac91fe63544e33568a3c744967b9360458101c3d9df096",
|
||||
"0xf994b38ba312d8bfb00d428b13a088738d93965b525eae81b45b9be344f99fd2",
|
||||
"0x0721f3f772958d6a58dba638453b8d004e0c76dc8b4cf6d595b712edddcf002f",
|
||||
"0x3c650c2c7ebbe7879a15882c3157552e8ae1adebea8f0c65a2dda272cc4ed838",
|
||||
"0x649fe38e87546703245a7adf5925e8c7a07942750e14d39553a56ca3fcbd8c65",
|
||||
"0xad204bf42d2a444faa864df8e9d023483a6b6daaa8001e00bb5373a45ed064a3",
|
||||
"0x2c5cdc73d8ddef2e5c0d47358ac180043e7e246e590a7e8ad2b0a3f9b4e9375d",
|
||||
"0xf38f6c364bbbbe626e849ca9bb9324c54cf0ba8dfc0b2741a3ff87ce7734adbc",
|
||||
"0x317efc1cea774849d6219d31c8464a15956da4f3810bf15d4353443f79d98e75",
|
||||
"0xb6796dccdf4d3cab16b5ec9567237cb988ee94131f3262c2a581180b775e76de",
|
||||
"0x1fde3fdf2303d080d400c43345a424f50f6551a6a06ad50c6e277d49e8034df3",
|
||||
"0x4d7bc44a3b56f5e69fd3e5e8c0cd8f5f839a775c4ee381b4b1d0a36656cf91cc",
|
||||
"0x6051b60fdced0c51aa6a1cab2418c8f21c5d174109d514a4c6de758b2056611b",
|
||||
"0x3c2f7be830078af3c2c6d1557b3da74d1d5bbfd8094f98886a959aa71ce70b15",
|
||||
"0x8f296b90a0ece0a3dbec19a801072497c5840f9c0491062cd402db00c2b69f2a",
|
||||
"0x6c14c4697f8291dbdfdbfea5522798e3f8b17204f80d8370e6d379e6ee659e77",
|
||||
"0x4e98f63afaa50f8a30b0d352eb5fcb5403c635cf54b41545aa8b48465d23fb1d",
|
||||
"0xad3059433e981ff12cd0d7dbc11a8d92a65cb39c6e936e9c7db5934d45806492",
|
||||
"0x1cbb21f28ad2d191d6850c97487e5a733306f2f6ba370723fd5ed37cf6c880a0",
|
||||
"0x82a0010a1b20d383bff0e5d7ba3751bc0d9161a4817554432558c5c2825babb3",
|
||||
"0x33e54e93443e87c003d582dc51d0b9981ddcaeac4df0993877739651cbf52a58",
|
||||
"0x1de8bc150f4142cd45b5d0784e5952abd8de7cba9654af959498c0fd0bcac404",
|
||||
"0x3ee852f48a1a930d671e53c9c8d8c3c38353ee1737c093960c3f841e6c682e94",
|
||||
"0xa9c6e05ec91e2a2f2f003419063fe033e37e5353c6e233706e29c08693e35eb8",
|
||||
"0x649f7328064c55c03249d527dadaedcdbb4cb0e939d94c866844192d99469e05",
|
||||
"0x3a407d00efcd5fe7bb765347b1a3f231b744349269b3aeb44099f4bdd068eb9e",
|
||||
"0xa1a20af2f7e61082810ce7e7afe6118bc0ad95e9641e6129027f46af28048107",
|
||||
"0x0d68fc5e58cacb2d16d99a0e9e612d674754ea51cbee2c68a21f4b0aa926688c",
|
||||
"0x9b3e58144c014343271c9dc90daa8d2f642954b3eda223d64bbb0ac41380e512",
|
||||
"0xd3de08b676d4f06bbf4322ed4340caab76e6ab7144c97af91c2bc9c749e65b38",
|
||||
"0x21d626c9c38087aac6262b64f09398be6e4cbf246100d8c2416cab57e9ac1b68",
|
||||
"0x563a450e35f40279f5946641a823f596ef3ad22a45b8ec280128546aeb0faf14",
|
||||
"0xadd9c7128e14e670c7d21d6dfa5c09a11dfd237e90709b087e3329d3cd89b5fd",
|
||||
"0x258cc0f845d8e7438a707f590f55203c6c51302cef4cfbf788b1c7054688da14",
|
||||
"0x4309676aa14fa8244e0a089c7013b89c9adf57fa952295b8ddb23fc6545c9870",
|
||||
"0x5db769765dfb41aefc0f40f06f3d005b30ce1f14f04f653e0c5500f651cd61cb",
|
||||
"0xbef131c9f19572b05d295d7122fd1a09fe4a8afd4e20c5a0f3cd2785b7eb9882",
|
||||
"0x3f235228ea537332a041ec75cc6cb5663edaa1c2ed1c1700273af73a5d49bf1c",
|
||||
"0xc081811bb077c6ebe224b560eb6b81f3f813b26789cb06d96110071ffc25fcb4",
|
||||
"0x912444c19a5e458b79c89969ed5336f2873267baf2fe729b6f218b74d269b797",
|
||||
"0x5846fc726eb9627e9d070041b92d76191c4b32e315d33ad18121b8acd01634fd",
|
||||
"0xc899f45494660034d343670856c13a32b230d047434a4d54a772132ddfe3e182",
|
||||
"0x11a699c18b04e8cdcd96a43b7465f7bd81f8f64d7ebe79dcaf9201cc897f2746",
|
||||
"0x8e09b134dc8a1735c060175e9688fd001974bf2e3baa5a8e88dc4c87365e0e07",
|
||||
"0xa086797ebca0a1d446a9289b7eda920b926e1b595c288a9dea31ad225e6de86f",
|
||||
"0x0cc04369b6036dff78a9856a5173bb2dde380359a8dbe0126e06d6e763a01c36",
|
||||
"0x4b5efcac86e03d1f67774769b8bcc5d131c181cd4fa297eaa6cea5ec0cdfaa6f",
|
||||
"0x47272a21a07ad5e14e3f97b237dab7e33344da4db5b2d31bc7cd0cc2d2c9f1db",
|
||||
"0x9540755fd321d125b73cb6f1884c2f0b2a821d29362194f5029a5e7ba2d3ed44",
|
||||
"0x229b88922fe52a78090673775f264cd665fe222002d6add2ed29b7ffd98de717",
|
||||
"0x8fa2d755d5cc0efb01d9fd6f5ae1f7864404ae111d8ba17e23686ea9b6566336",
|
||||
"0x33a8f2e0775fd19b1302b985bd6c29d4ab5fc63060bcf3df2c3685ab1b19ce67",
|
||||
"0xf6d6bebb541ef9b84d779c62adb76774bb38a8eba3823e74e0790dc7401bebbc",
|
||||
"0xa1f421108d49ed23996e55012613fc05e0f86e00f17251b1ff1e0824d35befc7",
|
||||
"0x2cc572ed83dc6c604bb455ab050c550184a923f4b13815f06d10ef19dffb3c7a",
|
||||
"0x28220e7d1a9583d68656f03ef4d6fa3e249c71d1b42698f87ba1fc582493e194",
|
||||
"0xe8aa37b3214abb1bc167fdb6f10119a4019541f31c76b3b3f8c363bb138bd09e",
|
||||
"0x825189c2c836dda454b457a03ff83d422bf78df1f368434768690fa7f51c57e0",
|
||||
"0x5dad65d275e69478c81ecaec5b872660205735d9649ac020f65f5ea6ae972dda",
|
||||
"0x84a1184d8f94fab280e0593479179348f9184d6fe5a2b2ea9697894c42574473",
|
||||
"0xbef5a05bc7e1fb94465570144499672d95f31fa241b4c510011f6677e2bf72fb",
|
||||
"0xd08235ebe6d79a8549bcd3d2414cd8afd2a3e2ca22ced226c60aacad1361ff89",
|
||||
"0xbab5204ad45ec52860023e7474579e7c95397f3c4ac01db7e446e92c19dceef0",
|
||||
"0x6c81acf2ff161d423a904c457166ff454ef41571d01e73d56bf9ab892790248d",
|
||||
"0xaf4a603b808e3ddece42e3e123ea02defb9f8ef2546a95c5a617b6ecdb89c306",
|
||||
"0xeecdbda25b04eb764e322d9a1e5eefad399c9ced8c77b1e4ecfbefcc90bb403d",
|
||||
"0x9463f4677a2039ca372b61b16d5bcb7c043b26af04aea4d3f0dcdec7bd222070",
|
||||
"0x27bfd92799b4cf9699d2bfcb158f6727bb986fc0dee780fc1052366ebc4e6364",
|
||||
"0x63c3faa1a8fc0d531261cd241b1299d4fc13629abb4cd357eeb130505fbddf94",
|
||||
"0x9a4535b07ff68862f3396b14b88fa07cff7abdd5744775aeeec6868606eb4712",
|
||||
"0xae59e7c3e0a1df32f6e027da2983d3c55b4ba4d99e85329361561bd7f13ac629",
|
||||
"0xcc5dc26b9be8fd8432537d967afe12fc668949e4fcf72d97a40f9214975fa57a",
|
||||
"0x8f11634c83c7a43be8b98335ba617a64c6379f5f92664055c5e1620791134ddb",
|
||||
"0x14ce2a69d844e6a46aa244c5aca9fb74c127f2151c7c16f4611ca030df365d8b",
|
||||
"0xb06f220566a5e62570b9e9e49a8b9d5663501ba145b12260fbf9d4a18a4b19e3",
|
||||
"0x6274f3cf553c45e6ba7ef644d75bf208e08a8c6325e336aefd35dda9cca3c4d2",
|
||||
"0xd0d685497c2f2b923d0b9f1590a748da8c684a915a470db58c3105c83d8304e7",
|
||||
"0xf37fab515f96e655f182f0b6e6aa3602f2cd74773329094772151e8c33d1f9a4",
|
||||
"0xf6efd731481e8553f1d18b5735166499e787009b484b0dfbe4d35e7930f0d837",
|
||||
"0xc96132b510863e553e08c54e98b5e9c0067f26e421980a6a3bfd4f07480c4396",
|
||||
"0xdca9d8182c573871b6d6a184cb9819256398080bcb7fd765e6c69cd972a28d8d",
|
||||
"0xd632ca6f5d45646726ecd2977ffea5c71a867890633f571b359657c0d096f840",
|
||||
"0xfe3884dbca6bd3b0087466b04e6a5857ad59d7a25021e1d994d059d20005185b",
|
||||
"0x7f40eb6fb94b05bb43873a98e9d4eb5f7ac90fb8913240bc0909c6be42922b30",
|
||||
"0x5113a0808666815cfc52b8ed63c649d96f35c365def36ae623f536241b163c3f",
|
||||
"0x8e6dbacfb5c593d7d7c2650d3d0115c3702cbb55f73011823a202e69ca33cc70",
|
||||
"0x8f069ac7caa48bce09fe93f4aaef6784d8a6f7a3a09edb82c7512ec18acc3ab9",
|
||||
"0xa5525e51fd789c59d3b208efffe09abca47cfd6981d36ab44084b86706c69888",
|
||||
"0xcb4a7e60d5e8b9d22887ef1e8ce339cfcea0ae1fcbfa9adb766ad05d84182de7",
|
||||
"0x0a14f23f9066ebdb67df31e66f6b8ab1c089025c0ba56ea56d15f73749f47cb7",
|
||||
"0x0963e3eba12e41d21af7625b8dc487b637b1789a6ac05fb23062e0166942df68",
|
||||
"0xcb7ec271b2f42cae0027d22b688b19b9288f2b5d9c43bc5b1ea23b35f5542828",
|
||||
"0x9b97e6f4b2eeee29ecccf9584dc020c8caa3cae51c82f5b58d279eaf0c6ab4e3",
|
||||
"0xad7f1963ce9993e6172c2ae90c6e1d4d3d3c52e14284fcc1b1e9a56776afb97e",
|
||||
"0x52ef2ad7bc2921742dcbac9772f13d5c31be938eb1ad6aceb2fa8a163389cefa",
|
||||
"0x369ead6d900e64ae0b5028df8574e59b67c61dca418c87ce6461eb4c8535fd30",
|
||||
"0x7e1a18f6199f05f21f9eb5463e9ffd87637d2fd24a23047fe095895c533cb6a5",
|
||||
"0xe1b8813a95e511aaec9b358d515e624fbc20e551c56328f843ae90b3c895d3a2",
|
||||
"0xc2ea59f3d1e7bbe115390a4c210142fe9f9dcb1959764450f5b5292ad90e0fcf",
|
||||
"0x97d235c3f18e6819c08dab4efe66d0f11f0d06f8ffc9686e3f28400e057e6f4a",
|
||||
"0xea64f817770252b77b08ca2f579b440ec02e833fc88af7c9c96a8e1e07b2cb2c",
|
||||
"0x185f5fd1f7001b533dc01783c83b7ab0828a4e2f188cc4e26768c515b4c421f6",
|
||||
"0x0c9de9844e856a1e4340bf54dcaf9dc66b489304765b5c3c6ca20284f5a0dca6",
|
||||
"0x4dd1d52da1d260d1f0f63bafc4c816b30cea8ec3434e7d4b63a0eff86997254c",
|
||||
"0x0b3eb94aa246f7c8c871535ae2d3abe5c1b951e76b77510140ef52d5ea2457ee",
|
||||
"0x27102708eea5d715799642f213049d8ac9abc3b12c76d147ce443dab28af96d8",
|
||||
"0x81fb3c4e8dc6c658af2901b7aebf7467b9ae045dd0f58fe8d77f8770ac517fb6",
|
||||
"0xf68dba4eee635d7494bae6fb9f0c44e739b3121d4bc6f6f21b495a716af3cf52",
|
||||
"0xcf87b723dc473d313bf9ddfa233056036c5658777e831796f1f56647cd040c8d",
|
||||
"0x49927c2100039ac496d9c16dd12f0a05c9441b8616c69c726fd2e79ae65e130c",
|
||||
"0x088195c7251f6b9fa2105e77df5620211b8ca783a77f1a98de6752fc442c26c7",
|
||||
"0x604de480bcb88e908b90451c4142b99b9cbb479167473befca7bea9b4ca427a3",
|
||||
"0x642fdaf6bc1abbf261a9480fcf9bb48cf03fb80bdd434c6ab63401856c74fa39",
|
||||
"0xe6b596393fce7a3023a316ac34a1fac18e18779ca5983791866f857f257592e1",
|
||||
"0x40384a52564fae5df8c3e41827cdf584e38f3f555a54ca749b7b516619071d85",
|
||||
"0xe52f7c17a4106594563ae7b724e5613e87d8442177f39a36b946b0e335be0e5b",
|
||||
"0x7726202a7c255a9d7be47af6f3b44c1e379cda61237866554396fb6ec043482c",
|
||||
"0x665da353f296cde80e3cbcb9c7f93b107d5676e5cd694b0bd33334d74789beb9"
|
||||
]
|
||||
},
|
||||
"nodes": [
|
||||
|
@ -27,8 +27,7 @@
|
||||
"eip161abcTransition": "0x7fffffffffffffff",
|
||||
"eip161dTransition": "0x7fffffffffffffff",
|
||||
"eip155Transition": "0x0",
|
||||
"eip98Transition": "0x7fffffffffffff",
|
||||
"eip86Transition": "0x7fffffffffffff"
|
||||
"eip98Transition": "0x7fffffffffffff"
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit b6011c3fb567d7178915574de0a8d4b5331fe725
|
||||
Subproject commit 3f5febc901913ef698f1b09dda8705babd729e4a
|
468
ethcore/res/ethereum/tests-issues/currents.json
Normal file
468
ethcore/res/ethereum/tests-issues/currents.json
Normal file
@ -0,0 +1,468 @@
|
||||
{ "block":
|
||||
[
|
||||
{
|
||||
"reference": "9590",
|
||||
"failing": "stCreateTest",
|
||||
"subtests": [
|
||||
"CreateOOGafterInitCodeReturndata2_d0g1v0_Constantinople"
|
||||
]
|
||||
},
|
||||
{
|
||||
"reference": "9590",
|
||||
"failing": "stCreate2",
|
||||
"subtests": [
|
||||
"RevertDepthCreateAddressCollision_d0g1v0_Constantinople",
|
||||
"RevertDepthCreateAddressCollision_d1g1v1_Constantinople",
|
||||
"CREATE2_Suicide_d5g0v0_Constantinople",
|
||||
"CREATE2_Suicide_d7g0v0_Constantinople",
|
||||
"create2collisionSelfdestructedOOG_d2g0v0_Byzantium",
|
||||
"create2collisionSelfdestructedOOG_d2g0v0_Constantinople",
|
||||
"create2collisionNonce_d1g0v0_Byzantium",
|
||||
"create2collisionNonce_d1g0v0_Constantinople",
|
||||
"CreateMessageRevertedOOGInInit_d0g1v0_Constantinople",
|
||||
"create2callPrecompiles_d3g0v0_Constantinople",
|
||||
"create2collisionCode_d1g0v0_Byzantium",
|
||||
"create2collisionCode_d1g0v0_Constantinople",
|
||||
"create2collisionStorage_d0g0v0_Byzantium",
|
||||
"create2collisionStorage_d0g0v0_Constantinople",
|
||||
"create2callPrecompiles_d4g0v0_Constantinople",
|
||||
"create2collisionSelfdestructedRevert_d0g0v0_Byzantium",
|
||||
"create2collisionSelfdestructedRevert_d0g0v0_Constantinople",
|
||||
"CreateMessageReverted_d0g1v0_Constantinople",
|
||||
"RevertOpcodeCreate_d0g1v0_Constantinople",
|
||||
"CREATE2_Suicide_d11g0v0_Constantinople",
|
||||
"create2checkFieldsInInitcode_d5g0v0_Constantinople",
|
||||
"create2collisionSelfdestructedOOG_d1g0v0_Byzantium",
|
||||
"create2collisionSelfdestructedOOG_d1g0v0_Constantinople",
|
||||
"returndatacopy_following_create_d1g0v0_Constantinople",
|
||||
"RevertDepthCreate2OOG_d1g1v1_Constantinople",
|
||||
"create2collisionSelfdestructed_d2g0v0_Byzantium",
|
||||
"create2collisionSelfdestructed_d2g0v0_Constantinople",
|
||||
"create2callPrecompiles_d2g0v0_Constantinople",
|
||||
"create2InitCodes_d2g0v0_Constantinople",
|
||||
"create2collisionNonce_d2g0v0_Byzantium",
|
||||
"create2collisionNonce_d2g0v0_Constantinople",
|
||||
"create2collisionCode_d0g0v0_Byzantium",
|
||||
"create2collisionCode_d0g0v0_Constantinople",
|
||||
"CREATE2_Bounds_d0g0v0_Constantinople",
|
||||
"RevertDepthCreate2OOG_d0g0v0_Constantinople",
|
||||
"CREATE2_Suicide_d1g0v0_Constantinople",
|
||||
"CREATE2_Bounds3_d0g1v0_Constantinople",
|
||||
"create2collisionStorage_d2g0v0_Byzantium",
|
||||
"create2collisionStorage_d2g0v0_Constantinople",
|
||||
"RevertDepthCreateAddressCollision_d0g0v1_Constantinople",
|
||||
"create2callPrecompiles_d5g0v0_Constantinople",
|
||||
"create2collisionCode2_d0g0v0_Byzantium",
|
||||
"create2collisionCode2_d0g0v0_Constantinople",
|
||||
"create2noCash_d0g0v0_Byzantium",
|
||||
"create2noCash_d0g0v0_Constantinople",
|
||||
"create2checkFieldsInInitcode_d7g0v0_Constantinople",
|
||||
"create2SmartInitCode_d1g0v0_Constantinople",
|
||||
"create2InitCodes_d6g0v0_Constantinople",
|
||||
"create2noCash_d1g0v0_Byzantium",
|
||||
"create2noCash_d1g0v0_Constantinople",
|
||||
"CREATE2_ContractSuicideDuringInit_ThenStoreThenReturn_d0g0v0_Constantinople",
|
||||
"RevertOpcodeInCreateReturns_d0g0v0_Constantinople",
|
||||
"create2collisionStorage_d1g0v0_Byzantium",
|
||||
"create2collisionStorage_d1g0v0_Constantinople",
|
||||
"create2checkFieldsInInitcode_d3g0v0_Constantinople",
|
||||
"create2collisionBalance_d0g0v0_Byzantium",
|
||||
"create2collisionBalance_d0g0v0_Constantinople",
|
||||
"create2collisionSelfdestructed2_d0g0v0_Constantinople",
|
||||
"create2InitCodes_d3g0v0_Constantinople",
|
||||
"create2collisionCode2_d1g0v0_Byzantium",
|
||||
"create2collisionCode2_d1g0v0_Constantinople",
|
||||
"create2checkFieldsInInitcode_d1g0v0_Constantinople",
|
||||
"create2collisionBalance_d1g0v0_Byzantium",
|
||||
"create2collisionBalance_d1g0v0_Constantinople",
|
||||
"CREATE2_Bounds3_d0g2v0_Constantinople",
|
||||
"create2callPrecompiles_d6g0v0_Constantinople",
|
||||
"Create2Recursive_d0g0v0_Constantinople",
|
||||
"create2collisionSelfdestructedOOG_d0g0v0_Byzantium",
|
||||
"create2collisionSelfdestructedOOG_d0g0v0_Constantinople",
|
||||
"CREATE2_Suicide_d3g0v0_Constantinople",
|
||||
"returndatacopy_following_create_d0g0v0_Constantinople",
|
||||
"create2InitCodes_d8g0v0_Constantinople",
|
||||
"RevertDepthCreate2OOG_d0g0v1_Constantinople",
|
||||
"create2checkFieldsInInitcode_d2g0v0_Constantinople",
|
||||
"RevertDepthCreate2OOG_d1g0v1_Constantinople",
|
||||
"Create2OnDepth1024_d0g0v0_Constantinople",
|
||||
"create2collisionSelfdestructed2_d1g0v0_Constantinople",
|
||||
"create2collisionSelfdestructedRevert_d2g0v0_Byzantium",
|
||||
"create2collisionSelfdestructedRevert_d2g0v0_Constantinople",
|
||||
"create2callPrecompiles_d0g0v0_Constantinople",
|
||||
"RevertDepthCreateAddressCollision_d0g1v1_Constantinople",
|
||||
"create2collisionSelfdestructed_d1g0v0_Byzantium",
|
||||
"create2collisionSelfdestructed_d1g0v0_Constantinople",
|
||||
"call_outsize_then_create2_successful_then_returndatasize_d0g0v0_Byzantium",
|
||||
"call_outsize_then_create2_successful_then_returndatasize_d0g0v0_Constantinople",
|
||||
"Create2OOGafterInitCodeRevert_d0g0v0_Constantinople",
|
||||
"Create2OOGafterInitCodeReturndata3_d0g0v0_Constantinople",
|
||||
"Create2OOGafterInitCodeReturndataSize_d0g0v0_Constantinople",
|
||||
"create2InitCodes_d7g0v0_Constantinople",
|
||||
"CREATE2_Suicide_d10g0v0_Constantinople",
|
||||
"RevertDepthCreate2OOG_d0g1v0_Constantinople",
|
||||
"create2InitCodes_d5g0v0_Constantinople",
|
||||
"create2collisionSelfdestructedRevert_d1g0v0_Byzantium",
|
||||
"create2collisionSelfdestructedRevert_d1g0v0_Constantinople",
|
||||
"RevertDepthCreate2OOG_d1g1v0_Constantinople",
|
||||
"create2collisionSelfdestructed_d0g0v0_Byzantium",
|
||||
"create2collisionSelfdestructed_d0g0v0_Constantinople",
|
||||
"create2noCash_d2g0v0_Byzantium",
|
||||
"create2noCash_d2g0v0_Constantinople",
|
||||
"CREATE2_Bounds3_d0g0v0_Constantinople",
|
||||
"create2collisionNonce_d0g0v0_Byzantium",
|
||||
"create2collisionNonce_d0g0v0_Constantinople",
|
||||
"CREATE2_Suicide_d2g0v0_Constantinople",
|
||||
"Create2OOGafterInitCode_d0g0v0_Constantinople",
|
||||
"call_then_create2_successful_then_returndatasize_d0g0v0_Byzantium",
|
||||
"call_then_create2_successful_then_returndatasize_d0g0v0_Constantinople",
|
||||
"create2collisionBalance_d2g0v0_Byzantium",
|
||||
"create2collisionBalance_d2g0v0_Constantinople",
|
||||
"create2checkFieldsInInitcode_d6g0v0_Constantinople",
|
||||
"RevertDepthCreate2OOG_d0g1v1_Constantinople",
|
||||
"returndatacopy_afterFailing_create_d0g0v0_Constantinople",
|
||||
"returndatacopy_following_revert_in_create_d0g0v0_Constantinople",
|
||||
"CREATE2_Suicide_d9g0v0_Constantinople",
|
||||
"create2callPrecompiles_d7g0v0_Constantinople",
|
||||
"RevertDepthCreateAddressCollision_d1g0v1_Constantinople",
|
||||
"create2InitCodes_d1g0v0_Constantinople",
|
||||
"CREATE2_Bounds_d0g1v0_Constantinople",
|
||||
"Create2OOGafterInitCodeReturndata_d0g0v0_Constantinople",
|
||||
"create2checkFieldsInInitcode_d4g0v0_Constantinople",
|
||||
"CreateMessageRevertedOOGInInit_d0g0v0_Constantinople",
|
||||
"RevertDepthCreateAddressCollision_d1g1v0_Constantinople",
|
||||
"returndatacopy_following_successful_create_d0g0v0_Constantinople",
|
||||
"create2checkFieldsInInitcode_d0g0v0_Constantinople",
|
||||
"CreateMessageReverted_d0g0v0_Constantinople",
|
||||
"create2SmartInitCode_d0g0v0_Constantinople",
|
||||
"CREATE2_Bounds2_d0g0v0_Constantinople",
|
||||
"returndatasize_following_successful_create_d0g0v0_Constantinople",
|
||||
"CREATE2_Bounds2_d0g1v0_Constantinople",
|
||||
"returndatacopy_0_0_following_successful_create_d0g0v0_Constantinople",
|
||||
"RevertDepthCreateAddressCollision_d0g0v0_Constantinople",
|
||||
"CREATE2_Suicide_d0g0v0_Constantinople",
|
||||
"create2InitCodes_d0g0v0_Constantinople",
|
||||
"Create2OnDepth1023_d0g0v0_Constantinople",
|
||||
"create2InitCodes_d4g0v0_Constantinople",
|
||||
"Create2OOGafterInitCodeReturndata2_d0g0v0_Constantinople",
|
||||
"create2collisionBalance_d3g0v0_Byzantium",
|
||||
"create2collisionBalance_d3g0v0_Constantinople",
|
||||
"CREATE2_Suicide_d4g0v0_Constantinople",
|
||||
"Create2OOGafterInitCode_d0g1v0_Constantinople",
|
||||
"RevertDepthCreateAddressCollision_d1g0v0_Constantinople",
|
||||
"Create2OOGafterInitCodeRevert2_d0g0v0_Constantinople",
|
||||
"Create2OOGafterInitCodeReturndata_d0g1v0_Constantinople",
|
||||
"Create2Recursive_d0g1v0_Constantinople",
|
||||
"create2collisionCode_d2g0v0_Byzantium",
|
||||
"create2collisionCode_d2g0v0_Constantinople",
|
||||
"CREATE2_Suicide_d6g0v0_Constantinople",
|
||||
"CREATE2_Suicide_d8g0v0_Constantinople",
|
||||
"RevertOpcodeCreate_d0g0v0_Constantinople",
|
||||
"Create2OOGafterInitCodeReturndata2_d0g1v0_Constantinople",
|
||||
"create2callPrecompiles_d1g0v0_Constantinople",
|
||||
"RevertInCreateInInit_d0g0v0_Constantinople",
|
||||
"RevertDepthCreate2OOG_d1g0v0_Constantinople"
|
||||
]
|
||||
},
|
||||
{
|
||||
"reference": "9590",
|
||||
"failing": "bcStateTest",
|
||||
"subtests": [
|
||||
"suicideStorageCheck_Byzantium",
|
||||
"suicideStorageCheck_Constantinople",
|
||||
"suicideStorageCheckVCreate2_Byzantium",
|
||||
"suicideStorageCheckVCreate2_Constantinople",
|
||||
"create2collisionwithSelfdestructSameBlock_Constantinople",
|
||||
"blockhashNonConstArg_Constantinople",
|
||||
"suicideThenCheckBalance_Constantinople",
|
||||
"suicideThenCheckBalance_Homestead",
|
||||
"suicideStorageCheckVCreate_Byzantium",
|
||||
"suicideStorageCheckVCreate_Constantinople"
|
||||
]
|
||||
},
|
||||
{
|
||||
"reference": "9590",
|
||||
"failing": "stEIP158Specific",
|
||||
"subtests": [
|
||||
"callToEmptyThenCallError_d0g0v0_Byzantium",
|
||||
"callToEmptyThenCallError_d0g0v0_Constantinople",
|
||||
"callToEmptyThenCallError_d0g0v0_EIP158"
|
||||
]
|
||||
},
|
||||
{
|
||||
"reference": "9590",
|
||||
"failing": "stPreCompiledContracts",
|
||||
"subtests": [
|
||||
"identity_to_smaller_d0g0v0_Constantinople",
|
||||
"identity_to_bigger_d0g0v0_Constantinople"
|
||||
]
|
||||
},
|
||||
{
|
||||
"reference": "9590",
|
||||
"failing": "stReturnDataTest",
|
||||
"subtests": [
|
||||
"modexp_modsize0_returndatasize_d0g1v0_Constantinople",
|
||||
"modexp_modsize0_returndatasize_d0g2v0_Constantinople",
|
||||
"modexp_modsize0_returndatasize_d0g3v0_Constantinople"
|
||||
]
|
||||
},
|
||||
{
|
||||
"reference": "9590",
|
||||
"failing": "stSpecialTest",
|
||||
"subtests": [
|
||||
"push32withoutByte_d0g0v0_Constantinople"
|
||||
]
|
||||
}
|
||||
|
||||
],
|
||||
"state":
|
||||
[
|
||||
{
|
||||
"reference": "9590",
|
||||
"failing": "stCreateTest",
|
||||
"subtests": {
|
||||
"CreateOOGafterInitCodeReturndata2": {
|
||||
"subnumbers": ["2"],
|
||||
"chain": "Constantinople (test)"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"reference": "9590",
|
||||
"failing": "stCreate2Test",
|
||||
"subtests": {
|
||||
"RevertInCreateInInit": {
|
||||
"subnumbers": ["1"],
|
||||
"chain": "Constantinople (test)"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"reference": "9590",
|
||||
"failing": "stEIP150Specific",
|
||||
"subtests": {
|
||||
"NewGasPriceForCodes": {
|
||||
"subnumbers": ["1"],
|
||||
"chain": "Constantinople (test)"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"reference": "9590",
|
||||
"failing": "stInitCodeTest",
|
||||
"subtests": {
|
||||
"OutOfGasContractCreation": {
|
||||
"subnumbers": ["4"],
|
||||
"chain": "Constantinople (test)"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"reference": "9590",
|
||||
"failing": "stPreCompiledContracts",
|
||||
"subtests": {
|
||||
"modexp": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"reference": "9590",
|
||||
"failing": "stRevertTest",
|
||||
"subtests": {
|
||||
"LoopCallsDepthThenRevert3": {
|
||||
"subnumbers": ["1"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"RevertOpcodeCreate": {
|
||||
"subnumbers": ["1"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"RevertSubCallStorageOOG2": {
|
||||
"subnumbers": ["1","3"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"RevertDepthCreateOOG": {
|
||||
"subnumbers": ["3","4"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"RevertOpcodeMultipleSubCalls": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"RevertOpcodeDirectCall": {
|
||||
"subnumbers": ["1","2"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"LoopCallsDepthThenRevert2": {
|
||||
"subnumbers": ["1"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"RevertDepth2": {
|
||||
"subnumbers": ["1"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"RevertRemoteSubCallStorageOOG2": {
|
||||
"subnumbers": ["1","2"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"RevertDepthCreateAddressCollision": {
|
||||
"subnumbers": ["3","4"],
|
||||
"chain": "Constantinople (test)"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"reference": "9590",
|
||||
"failing": "stStaticCall",
|
||||
"subtests": {
|
||||
"static_RevertDepth2": {
|
||||
"subnumbers": ["1","3"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"static_CheckOpcodes4": {
|
||||
"subnumbers": ["3"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"static_CheckOpcodes3": {
|
||||
"subnumbers": ["5","6","7","8"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"static_callBasic": {
|
||||
"subnumbers": ["1","2"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"static_CheckOpcodes2": {
|
||||
"subnumbers": ["5","6","7","8"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"static_callCreate": {
|
||||
"subnumbers": ["2"],
|
||||
"chain": "Constantinople (test)"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"reference": "https://github.com/ethereum/tests/issues/512",
|
||||
"failing": "stZeroKnowledge",
|
||||
"subtests": {
|
||||
"pointAddTrunc": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"pointAdd": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"pointMulAdd": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"pointMulAdd2": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"reference": "9590",
|
||||
"failing": "stCreate2Test",
|
||||
"subtests": {
|
||||
"call_then_create2_successful_then_returndatasize": {
|
||||
"subnumbers": ["1"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"returndatacopy_afterFailing_create": {
|
||||
"subnumbers": ["1"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"create2checkFieldsInInitcode": {
|
||||
"subnumbers": ["1","2","3","5","6","7"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"Create2Recursive": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"create2collisionBalance": {
|
||||
"subnumbers": ["2","3"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"create2InitCodes": {
|
||||
"subnumbers": ["1","5","6","7","8","9"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"Create2OOGafterInitCode": {
|
||||
"subnumbers": ["2"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"CreateMessageRevertedOOGInInit": {
|
||||
"subnumbers": ["2"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"returndatacopy_following_revert_in_create": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"create2collisionSelfdestructed": {
|
||||
"subnumbers": ["2"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"returndatacopy_0_0_following_successful_create": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"Create2OnDepth1023": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"Create2OOGafterInitCodeReturndata2": {
|
||||
"subnumbers": ["2"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"RevertOpcodeInCreateReturns": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"CREATE2_ContractSuicideDuringInit_ThenStoreThenReturn": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"returndatasize_following_successful_create": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"call_outsize_then_create2_successful_then_returndatasize": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"CreateMessageReverted": {
|
||||
"subnumbers": ["2"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"CREATE2_Suicide": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"Create2OOGafterInitCodeRevert": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"Create2OnDepth1024": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"create2collisionStorage": {
|
||||
"subnumbers": ["2","3"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"create2callPrecompiles": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -16,7 +16,16 @@
|
||||
"gasLimitBoundDivisor": "0x400",
|
||||
"minGasLimit": "0x1388",
|
||||
"networkID": "0x62121",
|
||||
"wasmActivationTransition": 4000000
|
||||
"wasmActivationTransition": 7250000,
|
||||
"eip140Transition": 7250000,
|
||||
"eip211Transition": 7250000,
|
||||
"eip214Transition": 7250000,
|
||||
"eip658Transition": 7250000,
|
||||
|
||||
"maxCodeSize": 24576,
|
||||
"maxCodeSizeTransition": 7250000,
|
||||
|
||||
"registrar": "0xb8624dc8cb3ca3147c178ac4c21734eb49e04071"
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
@ -43,12 +52,22 @@
|
||||
},
|
||||
"0x4ba15b56452521c0826a35a6f2022e1210fc519b": {
|
||||
"balance": "0x7E37BE2022B2B09472D89C0000"
|
||||
}
|
||||
},
|
||||
|
||||
"0x0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "activate_at": 7250000, "pricing": { "linear": { "base": 3000, "word": 0 } } } },
|
||||
"0x0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "activate_at": 7250000, "pricing": { "linear": { "base": 60, "word": 12 } } } },
|
||||
"0x0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "activate_at": 7250000, "pricing": { "linear": { "base": 600, "word": 120 } } } },
|
||||
"0x0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "activate_at": 7250000, "pricing": { "linear": { "base": 15, "word": 3 } } } },
|
||||
"0x0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": 7250000, "pricing": { "modexp": { "divisor": 20 } } } },
|
||||
"0x0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": 7250000, "pricing": { "linear": { "base": 500, "word": 0 } } } },
|
||||
"0x0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": 7250000, "pricing": { "linear": { "base": 40000, "word": 0 } } } },
|
||||
"0x0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": 7250000, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }
|
||||
},
|
||||
|
||||
"nodes": [
|
||||
"enode://147573f46fe9f5cc38fbe070089a31390baec5dd2827c8f2ef168833e4d0254fbee3969a02c5b9910ea5d5b23d86a6ed5eabcda17cc12007b7d9178b6c697aa5@37.120.168.56:30303",
|
||||
"enode://a370d5fd55959f20af6d1565b151a760c1372f5a2aaf674d4892cd4fd2de0d1f672781cd40e0d4e4b51c5823527ddec73b31cc14ac685449d9f0866996a16b9f@13.76.165.180:30303",
|
||||
"enode://da019fa5fb1fda105100d68a986938ec15ac5c6ff69d6e4ad3e350e377057f3e67e33aea5feb22d5cdcfc22041d141c8453c77baa64a216fff98f191ca76b3ec@18.220.108.238:30303",
|
||||
"enode://49498fb8cdcd79c813ccdaa9496a3a4be0a187a3183e99adbc04d9c90b9a62ad59f0b6832f6e43b48e63fbebf74ec5438eb0d6d9098330edf36413d276fedf81@13.80.148.117:30303"
|
||||
"enode://eda34244538d72f42605a6fc8b8a34b15714c683989e8b29dc9e7a2b2088da490a5b32f2c149bec5a5c482bf03ec2c4f38b833ae31e36fcb26fb05fd094b2a88@18.197.33.9:30303",
|
||||
"enode://12e903e900137b02b22e01f7918bd6e7310773c313e4e577281f35597e394a3e0b54c7314a8970a9776c5a3e5dc4daee289215dea3897bcb6d5cf0bb1dd2d356@18.197.31.231:30303",
|
||||
"enode://423fdb91b37ec0714af0c19f625ec4af3ada2844367a36e45a05703577a84f7f0e9483585d4950a35c9e3738dba8c6abd7e1ce278d9a1f3f28065bc009f409cd@52.221.203.209:30303",
|
||||
"enode://a9327d37d07799817d4a3e13d49fb4f5cc1486d4adf3ec8a6b98be62c4d7a5453914a5139dbe124809a388514cb0be37f9fa799539abe2250672f6d3d778b821@18.191.209.251:30303"
|
||||
]
|
||||
}
|
||||
|
@ -16,7 +16,6 @@
|
||||
"eip161dTransition": "0x0",
|
||||
"eip155Transition": "0x0",
|
||||
"eip98Transition": "0x7fffffffffffff",
|
||||
"eip86Transition": "0x7fffffffffffff",
|
||||
"maxCodeSize": 24576,
|
||||
"maxCodeSizeTransition": "0x0",
|
||||
"eip140Transition": "0x0",
|
||||
|
@ -11,7 +11,6 @@
|
||||
"maximumExtraDataSize": "0x20",
|
||||
"minGasLimit": "0x1388",
|
||||
"networkID" : "0x2",
|
||||
"eip86Transition": "0x7fffffffffffff",
|
||||
"eip140Transition": "0x0",
|
||||
"eip211Transition": "0x0",
|
||||
"eip214Transition": "0x0",
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 474110de59a0f632b20615256c913b144c49354c
|
||||
Subproject commit 0edbf860ff7ed4b6b6336097ba44836e8c6482dd
|
@ -94,6 +94,7 @@ impl ClientService {
|
||||
|
||||
let pruning = config.pruning;
|
||||
let client = Client::new(config, &spec, blockchain_db.clone(), miner.clone(), io_service.channel())?;
|
||||
miner.set_io_channel(io_service.channel());
|
||||
|
||||
let snapshot_params = SnapServiceParams {
|
||||
engine: spec.engine.clone(),
|
||||
|
@ -18,9 +18,9 @@
|
||||
|
||||
mod stores;
|
||||
|
||||
use self::stores::{AddressBook, DappsSettingsStore, NewDappsPolicy};
|
||||
use self::stores::AddressBook;
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use std::time::{Instant, Duration};
|
||||
|
||||
@ -96,20 +96,6 @@ impl From<SSError> for SignError {
|
||||
/// `AccountProvider` errors.
|
||||
pub type Error = SSError;
|
||||
|
||||
/// Dapp identifier
|
||||
#[derive(Default, Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
|
||||
pub struct DappId(String);
|
||||
|
||||
impl From<DappId> for String {
|
||||
fn from(id: DappId) -> String { id.0 }
|
||||
}
|
||||
impl From<String> for DappId {
|
||||
fn from(id: String) -> DappId { DappId(id) }
|
||||
}
|
||||
impl<'a> From<&'a str> for DappId {
|
||||
fn from(id: &'a str) -> DappId { DappId(id.to_owned()) }
|
||||
}
|
||||
|
||||
fn transient_sstore() -> EthMultiStore {
|
||||
EthMultiStore::open(Box::new(MemoryDirectory::default())).expect("MemoryDirectory load always succeeds; qed")
|
||||
}
|
||||
@ -125,8 +111,6 @@ pub struct AccountProvider {
|
||||
unlocked: RwLock<HashMap<StoreAccountRef, AccountData>>,
|
||||
/// Address book.
|
||||
address_book: RwLock<AddressBook>,
|
||||
/// Dapps settings.
|
||||
dapps_settings: RwLock<DappsSettingsStore>,
|
||||
/// Accounts on disk
|
||||
sstore: Box<SecretStore>,
|
||||
/// Accounts unlocked with rolling tokens
|
||||
@ -167,7 +151,7 @@ impl AccountProvider {
|
||||
/// Creates new account provider.
|
||||
pub fn new(sstore: Box<SecretStore>, settings: AccountProviderSettings) -> Self {
|
||||
let mut hardware_store = None;
|
||||
|
||||
|
||||
if settings.enable_hardware_wallets {
|
||||
match HardwareWalletManager::new() {
|
||||
Ok(manager) => {
|
||||
@ -195,7 +179,6 @@ impl AccountProvider {
|
||||
unlocked_secrets: RwLock::new(HashMap::new()),
|
||||
unlocked: RwLock::new(HashMap::new()),
|
||||
address_book: RwLock::new(address_book),
|
||||
dapps_settings: RwLock::new(DappsSettingsStore::new(&sstore.local_path())),
|
||||
sstore: sstore,
|
||||
transient_sstore: transient_sstore(),
|
||||
hardware_store: hardware_store,
|
||||
@ -210,7 +193,6 @@ impl AccountProvider {
|
||||
unlocked_secrets: RwLock::new(HashMap::new()),
|
||||
unlocked: RwLock::new(HashMap::new()),
|
||||
address_book: RwLock::new(AddressBook::transient()),
|
||||
dapps_settings: RwLock::new(DappsSettingsStore::transient()),
|
||||
sstore: Box::new(EthStore::open(Box::new(MemoryDirectory::default())).expect("MemoryDirectory load always succeeds; qed")),
|
||||
transient_sstore: transient_sstore(),
|
||||
hardware_store: None,
|
||||
@ -290,9 +272,14 @@ impl AccountProvider {
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns the address of default account.
|
||||
pub fn default_account(&self) -> Result<Address, Error> {
|
||||
Ok(self.accounts()?.first().cloned().unwrap_or_default())
|
||||
}
|
||||
|
||||
/// Returns addresses of hardware accounts.
|
||||
pub fn hardware_accounts(&self) -> Result<Vec<Address>, Error> {
|
||||
if let Some(accounts) = self.hardware_store.as_ref().map(|h| h.list_wallets()) {
|
||||
if let Some(accounts) = self.hardware_store.as_ref().map(|h| h.list_wallets()) {
|
||||
if !accounts.is_empty() {
|
||||
return Ok(accounts.into_iter().map(|a| a.address).collect());
|
||||
}
|
||||
@ -308,7 +295,7 @@ impl AccountProvider {
|
||||
Some(Ok(s)) => Ok(s),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Provide a pin to a locked hardware wallet on USB path to unlock it
|
||||
pub fn hardware_pin_matrix_ack(&self, path: &str, pin: &str) -> Result<bool, SignError> {
|
||||
match self.hardware_store.as_ref().map(|h| h.pin_matrix_ack(path, pin)) {
|
||||
@ -318,175 +305,6 @@ impl AccountProvider {
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets addresses of accounts exposed for unknown dapps.
|
||||
/// `None` means that all accounts will be visible.
|
||||
/// If not `None` or empty it will also override default account.
|
||||
pub fn set_new_dapps_addresses(&self, accounts: Option<Vec<Address>>) -> Result<(), Error> {
|
||||
let current_default = self.new_dapps_default_address()?;
|
||||
|
||||
self.dapps_settings.write().set_policy(match accounts {
|
||||
None => NewDappsPolicy::AllAccounts {
|
||||
default: current_default,
|
||||
},
|
||||
Some(accounts) => NewDappsPolicy::Whitelist(accounts),
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Gets addresses of accounts exposed for unknown dapps.
|
||||
/// `None` means that all accounts will be visible.
|
||||
pub fn new_dapps_addresses(&self) -> Result<Option<Vec<Address>>, Error> {
|
||||
Ok(match self.dapps_settings.read().policy() {
|
||||
NewDappsPolicy::AllAccounts { .. } => None,
|
||||
NewDappsPolicy::Whitelist(accounts) => Some(accounts),
|
||||
})
|
||||
}
|
||||
|
||||
/// Sets a default account for unknown dapps.
|
||||
/// This account will always be returned as the first one.
|
||||
pub fn set_new_dapps_default_address(&self, address: Address) -> Result<(), Error> {
|
||||
if !self.valid_addresses()?.contains(&address) {
|
||||
return Err(SSError::InvalidAccount.into());
|
||||
}
|
||||
|
||||
let mut settings = self.dapps_settings.write();
|
||||
let new_policy = match settings.policy() {
|
||||
NewDappsPolicy::AllAccounts { .. } => NewDappsPolicy::AllAccounts { default: address },
|
||||
NewDappsPolicy::Whitelist(list) => NewDappsPolicy::Whitelist(Self::insert_default(list, address)),
|
||||
};
|
||||
settings.set_policy(new_policy);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Inserts given address as first in the vector, preventing duplicates.
|
||||
fn insert_default(mut addresses: Vec<Address>, default: Address) -> Vec<Address> {
|
||||
if let Some(position) = addresses.iter().position(|address| address == &default) {
|
||||
addresses.swap(0, position);
|
||||
} else {
|
||||
addresses.insert(0, default);
|
||||
}
|
||||
|
||||
addresses
|
||||
}
|
||||
|
||||
/// Returns a list of accounts that new dapp should see.
|
||||
/// First account is always the default account.
|
||||
fn new_dapps_addresses_list(&self) -> Result<Vec<Address>, Error> {
|
||||
match self.dapps_settings.read().policy() {
|
||||
NewDappsPolicy::AllAccounts { default } => if default.is_zero() {
|
||||
self.accounts()
|
||||
} else {
|
||||
Ok(Self::insert_default(self.accounts()?, default))
|
||||
},
|
||||
NewDappsPolicy::Whitelist(accounts) => {
|
||||
let addresses = self.filter_addresses(accounts)?;
|
||||
if addresses.is_empty() {
|
||||
Ok(vec![self.accounts()?.get(0).cloned().unwrap_or(0.into())])
|
||||
} else {
|
||||
Ok(addresses)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets a default account for new dapps
|
||||
/// Will return zero address in case the default is not set and there are no accounts configured.
|
||||
pub fn new_dapps_default_address(&self) -> Result<Address, Error> {
|
||||
Ok(self.new_dapps_addresses_list()?
|
||||
.get(0)
|
||||
.cloned()
|
||||
.unwrap_or(0.into())
|
||||
)
|
||||
}
|
||||
|
||||
/// Gets a list of dapps recently requesting accounts.
|
||||
pub fn recent_dapps(&self) -> Result<HashMap<DappId, u64>, Error> {
|
||||
Ok(self.dapps_settings.read().recent_dapps())
|
||||
}
|
||||
|
||||
/// Marks dapp as recently used.
|
||||
pub fn note_dapp_used(&self, dapp: DappId) -> Result<(), Error> {
|
||||
let mut dapps = self.dapps_settings.write();
|
||||
dapps.mark_dapp_used(dapp.clone());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Gets addresses visible for given dapp.
|
||||
pub fn dapp_addresses(&self, dapp: DappId) -> Result<Vec<Address>, Error> {
|
||||
let accounts = self.dapps_settings.read().settings().get(&dapp).map(|settings| {
|
||||
(settings.accounts.clone(), settings.default.clone())
|
||||
});
|
||||
|
||||
match accounts {
|
||||
Some((Some(accounts), Some(default))) => self.filter_addresses(Self::insert_default(accounts, default)),
|
||||
Some((Some(accounts), None)) => self.filter_addresses(accounts),
|
||||
Some((None, Some(default))) => self.filter_addresses(Self::insert_default(self.new_dapps_addresses_list()?, default)),
|
||||
_ => self.new_dapps_addresses_list(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns default account for particular dapp falling back to other allowed accounts if necessary.
|
||||
pub fn dapp_default_address(&self, dapp: DappId) -> Result<Address, Error> {
|
||||
let dapp_default = self.dapp_addresses(dapp)?
|
||||
.get(0)
|
||||
.cloned();
|
||||
|
||||
match dapp_default {
|
||||
Some(default) => Ok(default),
|
||||
None => self.new_dapps_default_address(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets default address for given dapp.
|
||||
/// Does not alter dapp addresses, but this account will always be returned as the first one.
|
||||
pub fn set_dapp_default_address(&self, dapp: DappId, address: Address) -> Result<(), Error> {
|
||||
if !self.valid_addresses()?.contains(&address) {
|
||||
return Err(SSError::InvalidAccount.into());
|
||||
}
|
||||
|
||||
self.dapps_settings.write().set_default(dapp, address);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets addresses visible for given dapp.
|
||||
/// If `None` - falls back to dapps addresses
|
||||
/// If not `None` and not empty it will also override default account.
|
||||
pub fn set_dapp_addresses(&self, dapp: DappId, addresses: Option<Vec<Address>>) -> Result<(), Error> {
|
||||
let (addresses, default) = match addresses {
|
||||
Some(addresses) => {
|
||||
let addresses = self.filter_addresses(addresses)?;
|
||||
let default = addresses.get(0).cloned();
|
||||
(Some(addresses), default)
|
||||
},
|
||||
None => (None, None),
|
||||
};
|
||||
|
||||
let mut settings = self.dapps_settings.write();
|
||||
if let Some(default) = default {
|
||||
settings.set_default(dapp.clone(), default);
|
||||
}
|
||||
settings.set_accounts(dapp, addresses);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn valid_addresses(&self) -> Result<HashSet<Address>, Error> {
|
||||
Ok(self.addresses_info().into_iter()
|
||||
.map(|(address, _)| address)
|
||||
.chain(self.accounts()?)
|
||||
.collect())
|
||||
}
|
||||
|
||||
/// Removes addresses that are neither accounts nor in address book.
|
||||
fn filter_addresses(&self, addresses: Vec<Address>) -> Result<Vec<Address>, Error> {
|
||||
let valid = self.valid_addresses()?;
|
||||
|
||||
Ok(addresses.into_iter()
|
||||
.filter(|a| valid.contains(&a))
|
||||
.collect()
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns each address along with metadata.
|
||||
pub fn addresses_info(&self) -> HashMap<Address, AccountMeta> {
|
||||
self.address_book.read().get()
|
||||
@ -849,7 +667,7 @@ impl AccountProvider {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{AccountProvider, Unlock, DappId};
|
||||
use super::{AccountProvider, Unlock};
|
||||
use std::time::{Duration, Instant};
|
||||
use ethstore::ethkey::{Generator, Random, Address};
|
||||
use ethstore::{StoreAccountRef, Derivation};
|
||||
@ -977,96 +795,6 @@ mod tests {
|
||||
assert!(ap.sign_with_token(kp.address(), token, Default::default()).is_err(), "Second usage of the same token should fail.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_reset_dapp_addresses_to_default() {
|
||||
// given
|
||||
let ap = AccountProvider::transient_provider();
|
||||
let app = DappId("app1".into());
|
||||
// add accounts to address book
|
||||
ap.set_address_name(1.into(), "1".into());
|
||||
ap.set_address_name(2.into(), "2".into());
|
||||
// set `AllAccounts` policy
|
||||
ap.set_new_dapps_addresses(Some(vec![1.into(), 2.into()])).unwrap();
|
||||
assert_eq!(ap.dapp_addresses(app.clone()).unwrap(), vec![1.into(), 2.into()]);
|
||||
|
||||
// Alter and check
|
||||
ap.set_dapp_addresses(app.clone(), Some(vec![1.into(), 3.into()])).unwrap();
|
||||
assert_eq!(ap.dapp_addresses(app.clone()).unwrap(), vec![1.into()]);
|
||||
|
||||
// Reset back to default
|
||||
ap.set_dapp_addresses(app.clone(), None).unwrap();
|
||||
assert_eq!(ap.dapp_addresses(app.clone()).unwrap(), vec![1.into(), 2.into()]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_set_dapps_default_address() {
|
||||
// given
|
||||
let ap = AccountProvider::transient_provider();
|
||||
let app = DappId("app1".into());
|
||||
// set `AllAccounts` policy
|
||||
ap.set_new_dapps_addresses(None).unwrap();
|
||||
// add accounts to address book
|
||||
ap.set_address_name(1.into(), "1".into());
|
||||
ap.set_address_name(2.into(), "2".into());
|
||||
|
||||
ap.set_dapp_addresses(app.clone(), Some(vec![1.into(), 2.into(), 3.into()])).unwrap();
|
||||
assert_eq!(ap.dapp_addresses(app.clone()).unwrap(), vec![1.into(), 2.into()]);
|
||||
assert_eq!(ap.dapp_default_address("app1".into()).unwrap(), 1.into());
|
||||
|
||||
// when setting empty list
|
||||
ap.set_dapp_addresses(app.clone(), Some(vec![])).unwrap();
|
||||
|
||||
// then default account is intact
|
||||
assert_eq!(ap.dapp_addresses(app.clone()).unwrap(), vec![1.into()]);
|
||||
assert_eq!(ap.dapp_default_address("app1".into()).unwrap(), 1.into());
|
||||
|
||||
// alter default account
|
||||
ap.set_dapp_default_address("app1".into(), 2.into()).unwrap();
|
||||
assert_eq!(ap.dapp_addresses(app.clone()).unwrap(), vec![2.into()]);
|
||||
assert_eq!(ap.dapp_default_address("app1".into()).unwrap(), 2.into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_set_dapps_policy_and_default_account() {
|
||||
// given
|
||||
let ap = AccountProvider::transient_provider();
|
||||
|
||||
// default_account should be always available
|
||||
assert_eq!(ap.new_dapps_default_address().unwrap(), 0.into());
|
||||
|
||||
let address = ap.new_account(&"test".into()).unwrap();
|
||||
ap.set_address_name(1.into(), "1".into());
|
||||
|
||||
// Default account set to first account by default
|
||||
assert_eq!(ap.new_dapps_default_address().unwrap(), address);
|
||||
assert_eq!(ap.dapp_default_address("app1".into()).unwrap(), address);
|
||||
|
||||
// Even when returning nothing
|
||||
ap.set_new_dapps_addresses(Some(vec![])).unwrap();
|
||||
// Default account is still returned
|
||||
assert_eq!(ap.dapp_addresses("app1".into()).unwrap(), vec![address]);
|
||||
|
||||
// change to all
|
||||
ap.set_new_dapps_addresses(None).unwrap();
|
||||
assert_eq!(ap.dapp_addresses("app1".into()).unwrap(), vec![address]);
|
||||
|
||||
// change to non-existent account
|
||||
ap.set_new_dapps_addresses(Some(vec![2.into()])).unwrap();
|
||||
assert_eq!(ap.dapp_addresses("app1".into()).unwrap(), vec![address]);
|
||||
|
||||
// change to a addresses
|
||||
ap.set_new_dapps_addresses(Some(vec![1.into()])).unwrap();
|
||||
assert_eq!(ap.dapp_addresses("app1".into()).unwrap(), vec![1.into()]);
|
||||
|
||||
// it overrides default account
|
||||
assert_eq!(ap.new_dapps_default_address().unwrap(), 1.into());
|
||||
assert_eq!(ap.dapp_default_address("app1".into()).unwrap(), 1.into());
|
||||
|
||||
ap.set_new_dapps_default_address(address).unwrap();
|
||||
assert_eq!(ap.new_dapps_default_address().unwrap(), address);
|
||||
assert_eq!(ap.dapp_default_address("app1".into()).unwrap(), address);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_return_blacklisted_account() {
|
||||
// given
|
||||
|
@ -14,21 +14,14 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Address Book and Dapps Settings Store
|
||||
//! Address Book Store
|
||||
|
||||
use std::{fs, fmt, hash, ops};
|
||||
use std::sync::atomic::{self, AtomicUsize};
|
||||
use std::collections::HashMap;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use ethstore::ethkey::Address;
|
||||
use ethjson::misc::{
|
||||
AccountMeta,
|
||||
DappsSettings as JsonSettings,
|
||||
DappsHistory as JsonDappsHistory,
|
||||
NewDappsPolicy as JsonNewDappsPolicy,
|
||||
};
|
||||
use account_provider::DappId;
|
||||
use ethjson::misc::AccountMeta;
|
||||
|
||||
/// Disk-backed map from Address to String. Uses JSON.
|
||||
pub struct AddressBook {
|
||||
@ -88,214 +81,6 @@ impl AddressBook {
|
||||
}
|
||||
}
|
||||
|
||||
/// Dapps user settings
|
||||
#[derive(Debug, Default, Clone, Eq, PartialEq)]
|
||||
pub struct DappsSettings {
|
||||
/// A list of visible accounts
|
||||
pub accounts: Option<Vec<Address>>,
|
||||
/// Default account
|
||||
pub default: Option<Address>,
|
||||
}
|
||||
|
||||
impl From<JsonSettings> for DappsSettings {
|
||||
fn from(s: JsonSettings) -> Self {
|
||||
DappsSettings {
|
||||
accounts: s.accounts.map(|accounts| accounts.into_iter().map(Into::into).collect()),
|
||||
default: s.default.map(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DappsSettings> for JsonSettings {
|
||||
fn from(s: DappsSettings) -> Self {
|
||||
JsonSettings {
|
||||
accounts: s.accounts.map(|accounts| accounts.into_iter().map(Into::into).collect()),
|
||||
default: s.default.map(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Dapps user settings
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub enum NewDappsPolicy {
|
||||
AllAccounts {
|
||||
default: Address,
|
||||
},
|
||||
Whitelist(Vec<Address>),
|
||||
}
|
||||
|
||||
impl From<JsonNewDappsPolicy> for NewDappsPolicy {
|
||||
fn from(s: JsonNewDappsPolicy) -> Self {
|
||||
match s {
|
||||
JsonNewDappsPolicy::AllAccounts { default } => NewDappsPolicy::AllAccounts {
|
||||
default: default.into(),
|
||||
},
|
||||
JsonNewDappsPolicy::Whitelist(accounts) => NewDappsPolicy::Whitelist(
|
||||
accounts.into_iter().map(Into::into).collect()
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<NewDappsPolicy> for JsonNewDappsPolicy {
|
||||
fn from(s: NewDappsPolicy) -> Self {
|
||||
match s {
|
||||
NewDappsPolicy::AllAccounts { default } => JsonNewDappsPolicy::AllAccounts {
|
||||
default: default.into(),
|
||||
},
|
||||
NewDappsPolicy::Whitelist(accounts) => JsonNewDappsPolicy::Whitelist(
|
||||
accounts.into_iter().map(Into::into).collect()
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Transient dapps data
|
||||
#[derive(Default, Debug, Clone, Eq, PartialEq)]
|
||||
pub struct TransientDappsData {
|
||||
/// Timestamp of last access
|
||||
pub last_accessed: u64,
|
||||
}
|
||||
|
||||
impl From<JsonDappsHistory> for TransientDappsData {
|
||||
fn from(s: JsonDappsHistory) -> Self {
|
||||
TransientDappsData {
|
||||
last_accessed: s.last_accessed,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TransientDappsData> for JsonDappsHistory {
|
||||
fn from(s: TransientDappsData) -> Self {
|
||||
JsonDappsHistory {
|
||||
last_accessed: s.last_accessed,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum TimeProvider {
|
||||
Clock,
|
||||
Incremenetal(AtomicUsize)
|
||||
}
|
||||
|
||||
impl TimeProvider {
|
||||
fn get(&self) -> u64 {
|
||||
match *self {
|
||||
TimeProvider::Clock => {
|
||||
::std::time::UNIX_EPOCH.elapsed()
|
||||
.expect("Correct time is required to be set")
|
||||
.as_secs()
|
||||
|
||||
},
|
||||
TimeProvider::Incremenetal(ref time) => {
|
||||
time.fetch_add(1, atomic::Ordering::SeqCst) as u64
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const MAX_RECENT_DAPPS: usize = 50;
|
||||
|
||||
/// Disk-backed map from DappId to Settings. Uses JSON.
|
||||
pub struct DappsSettingsStore {
|
||||
/// Dapps Settings
|
||||
settings: DiskMap<DappId, DappsSettings>,
|
||||
/// New Dapps Policy
|
||||
policy: DiskMap<String, NewDappsPolicy>,
|
||||
/// Transient Data of recently Accessed Dapps
|
||||
history: DiskMap<DappId, TransientDappsData>,
|
||||
/// Time
|
||||
time: TimeProvider,
|
||||
}
|
||||
|
||||
impl DappsSettingsStore {
|
||||
/// Creates new store at given directory path.
|
||||
pub fn new(path: &Path) -> Self {
|
||||
let mut r = DappsSettingsStore {
|
||||
settings: DiskMap::new(path, "dapps_accounts.json".into()),
|
||||
policy: DiskMap::new(path, "dapps_policy.json".into()),
|
||||
history: DiskMap::new(path, "dapps_history.json".into()),
|
||||
time: TimeProvider::Clock,
|
||||
};
|
||||
r.settings.revert(JsonSettings::read);
|
||||
r.policy.revert(JsonNewDappsPolicy::read);
|
||||
r.history.revert(JsonDappsHistory::read);
|
||||
r
|
||||
}
|
||||
|
||||
/// Creates transient store (no changes are saved to disk).
|
||||
pub fn transient() -> Self {
|
||||
DappsSettingsStore {
|
||||
settings: DiskMap::transient(),
|
||||
policy: DiskMap::transient(),
|
||||
history: DiskMap::transient(),
|
||||
time: TimeProvider::Incremenetal(AtomicUsize::new(1)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get copy of the dapps settings
|
||||
pub fn settings(&self) -> HashMap<DappId, DappsSettings> {
|
||||
self.settings.clone()
|
||||
}
|
||||
|
||||
/// Returns current new dapps policy
|
||||
pub fn policy(&self) -> NewDappsPolicy {
|
||||
self.policy.get("default").cloned().unwrap_or(NewDappsPolicy::AllAccounts {
|
||||
default: 0.into(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns recent dapps with last accessed timestamp
|
||||
pub fn recent_dapps(&self) -> HashMap<DappId, u64> {
|
||||
self.history.iter().map(|(k, v)| (k.clone(), v.last_accessed)).collect()
|
||||
}
|
||||
|
||||
/// Marks recent dapp as used
|
||||
pub fn mark_dapp_used(&mut self, dapp: DappId) {
|
||||
{
|
||||
let entry = self.history.entry(dapp).or_insert_with(|| Default::default());
|
||||
entry.last_accessed = self.time.get();
|
||||
}
|
||||
// Clear extraneous entries
|
||||
while self.history.len() > MAX_RECENT_DAPPS {
|
||||
let min = self.history.iter()
|
||||
.min_by_key(|&(_, ref v)| v.last_accessed)
|
||||
.map(|(ref k, _)| k.clone())
|
||||
.cloned();
|
||||
|
||||
match min {
|
||||
Some(k) => self.history.remove(&k),
|
||||
None => break,
|
||||
};
|
||||
}
|
||||
self.history.save(JsonDappsHistory::write);
|
||||
}
|
||||
|
||||
/// Sets current new dapps policy
|
||||
pub fn set_policy(&mut self, policy: NewDappsPolicy) {
|
||||
self.policy.insert("default".into(), policy);
|
||||
self.policy.save(JsonNewDappsPolicy::write);
|
||||
}
|
||||
|
||||
/// Sets accounts for specific dapp.
|
||||
pub fn set_accounts(&mut self, id: DappId, accounts: Option<Vec<Address>>) {
|
||||
{
|
||||
let settings = self.settings.entry(id).or_insert_with(DappsSettings::default);
|
||||
settings.accounts = accounts;
|
||||
}
|
||||
self.settings.save(JsonSettings::write);
|
||||
}
|
||||
|
||||
/// Sets a default account for specific dapp.
|
||||
pub fn set_default(&mut self, id: DappId, default: Address) {
|
||||
{
|
||||
let settings = self.settings.entry(id).or_insert_with(DappsSettings::default);
|
||||
settings.default = Some(default);
|
||||
}
|
||||
self.settings.save(JsonSettings::write);
|
||||
}
|
||||
}
|
||||
|
||||
/// Disk-serializable HashMap
|
||||
#[derive(Debug)]
|
||||
struct DiskMap<K: hash::Hash + Eq, V> {
|
||||
@ -366,8 +151,7 @@ impl<K: hash::Hash + Eq, V> DiskMap<K, V> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{AddressBook, DappsSettingsStore, DappsSettings, NewDappsPolicy};
|
||||
use account_provider::DappId;
|
||||
use super::AddressBook;
|
||||
use std::collections::HashMap;
|
||||
use ethjson::misc::AccountMeta;
|
||||
use tempdir::TempDir;
|
||||
@ -398,63 +182,4 @@ mod tests {
|
||||
3.into() => AccountMeta{name: "Three".to_owned(), meta: "{}".to_owned(), uuid: None}
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_save_and_reload_dapps_settings() {
|
||||
// given
|
||||
let tempdir = TempDir::new("").unwrap();
|
||||
let mut b = DappsSettingsStore::new(tempdir.path());
|
||||
|
||||
// when
|
||||
b.set_accounts("dappOne".into(), Some(vec![1.into(), 2.into()]));
|
||||
|
||||
// then
|
||||
let b = DappsSettingsStore::new(tempdir.path());
|
||||
assert_eq!(b.settings(), hash_map![
|
||||
"dappOne".into() => DappsSettings {
|
||||
accounts: Some(vec![1.into(), 2.into()]),
|
||||
default: None,
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_maintain_a_map_of_recent_dapps() {
|
||||
let mut store = DappsSettingsStore::transient();
|
||||
assert!(store.recent_dapps().is_empty(), "Initially recent dapps should be empty.");
|
||||
|
||||
let dapp1: DappId = "dapp1".into();
|
||||
let dapp2: DappId = "dapp2".into();
|
||||
store.mark_dapp_used(dapp1.clone());
|
||||
let recent = store.recent_dapps();
|
||||
assert_eq!(recent.len(), 1);
|
||||
assert_eq!(recent.get(&dapp1), Some(&1));
|
||||
|
||||
store.mark_dapp_used(dapp2.clone());
|
||||
let recent = store.recent_dapps();
|
||||
assert_eq!(recent.len(), 2);
|
||||
assert_eq!(recent.get(&dapp1), Some(&1));
|
||||
assert_eq!(recent.get(&dapp2), Some(&2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_store_dapps_policy() {
|
||||
// given
|
||||
let tempdir = TempDir::new("").unwrap();
|
||||
let mut store = DappsSettingsStore::new(tempdir.path());
|
||||
|
||||
// Test default policy
|
||||
assert_eq!(store.policy(), NewDappsPolicy::AllAccounts {
|
||||
default: 0.into(),
|
||||
});
|
||||
|
||||
// when
|
||||
store.set_policy(NewDappsPolicy::Whitelist(vec![1.into(), 2.into()]));
|
||||
|
||||
// then
|
||||
let store = DappsSettingsStore::new(tempdir.path());
|
||||
assert_eq!(store.policy.clone(), hash_map![
|
||||
"default".into() => NewDappsPolicy::Whitelist(vec![1.into(), 2.into()])
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ use encoded;
|
||||
use engines::epoch::{Transition as EpochTransition, PendingTransition as PendingEpochTransition};
|
||||
use engines::ForkChoice;
|
||||
use ethereum_types::{H256, Bloom, BloomRef, U256};
|
||||
use error::Error as EthcoreError;
|
||||
use header::*;
|
||||
use heapsize::HeapSizeOf;
|
||||
use itertools::Itertools;
|
||||
@ -60,6 +61,21 @@ pub trait BlockChainDB: Send + Sync {
|
||||
|
||||
/// Trace blooms database.
|
||||
fn trace_blooms(&self) -> &blooms_db::Database;
|
||||
|
||||
/// Restore the DB from the given path
|
||||
fn restore(&self, new_db: &str) -> Result<(), EthcoreError> {
|
||||
// First, close the Blooms databases
|
||||
self.blooms().close()?;
|
||||
self.trace_blooms().close()?;
|
||||
|
||||
// Restore the key_value DB
|
||||
self.key_value().restore(new_db)?;
|
||||
|
||||
// Re-open the Blooms databases
|
||||
self.blooms().reopen()?;
|
||||
self.trace_blooms().reopen()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Generic database handler. This trait contains one function `open`. When called, it opens database with a
|
||||
|
@ -15,7 +15,7 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::collections::{HashSet, BTreeMap, VecDeque};
|
||||
use std::fmt;
|
||||
use std::cmp;
|
||||
use std::str::FromStr;
|
||||
use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering};
|
||||
use std::sync::{Arc, Weak};
|
||||
@ -50,13 +50,16 @@ use client::{
|
||||
};
|
||||
use encoded;
|
||||
use engines::{EthEngine, EpochTransition, ForkChoice};
|
||||
use error::{ImportErrorKind, BlockImportErrorKind, ExecutionError, CallError, BlockError, ImportResult, Error as EthcoreError};
|
||||
use error::{
|
||||
ImportErrorKind, BlockImportErrorKind, ExecutionError, CallError, BlockError, ImportResult,
|
||||
QueueError, QueueErrorKind, Error as EthcoreError
|
||||
};
|
||||
use vm::{EnvInfo, LastHashes};
|
||||
use evm::Schedule;
|
||||
use executive::{Executive, Executed, TransactOptions, contract_address};
|
||||
use factory::{Factories, VmFactory};
|
||||
use header::{BlockNumber, Header, ExtendedHeader};
|
||||
use io::{IoChannel, IoError};
|
||||
use io::IoChannel;
|
||||
use log_entry::LocalizedLogEntry;
|
||||
use miner::{Miner, MinerService};
|
||||
use ethcore_miner::pool::VerifiedTransaction;
|
||||
@ -200,7 +203,7 @@ pub struct Client {
|
||||
|
||||
/// Flag changed by `sleep` and `wake_up` methods. Not to be confused with `enabled`.
|
||||
liveness: AtomicBool,
|
||||
io_channel: Mutex<IoChannel<ClientIoMessage>>,
|
||||
io_channel: RwLock<IoChannel<ClientIoMessage>>,
|
||||
|
||||
/// List of actors to be notified on certain chain events
|
||||
notify: RwLock<Vec<Weak<ChainNotify>>>,
|
||||
@ -761,7 +764,7 @@ impl Client {
|
||||
db: RwLock::new(db.clone()),
|
||||
state_db: RwLock::new(state_db),
|
||||
report: RwLock::new(Default::default()),
|
||||
io_channel: Mutex::new(message_channel),
|
||||
io_channel: RwLock::new(message_channel),
|
||||
notify: RwLock::new(Vec::new()),
|
||||
queue_transactions: IoChannelQueue::new(config.transaction_verification_queue_size),
|
||||
queue_ancient_blocks: IoChannelQueue::new(MAX_ANCIENT_BLOCKS_QUEUE_SIZE),
|
||||
@ -995,7 +998,7 @@ impl Client {
|
||||
|
||||
/// Replace io channel. Useful for testing.
|
||||
pub fn set_io_channel(&self, io_channel: IoChannel<ClientIoMessage>) {
|
||||
*self.io_channel.lock() = io_channel;
|
||||
*self.io_channel.write() = io_channel;
|
||||
}
|
||||
|
||||
/// Get a copy of the best block's state.
|
||||
@ -1293,9 +1296,7 @@ impl snapshot::DatabaseRestore for Client {
|
||||
let mut tracedb = self.tracedb.write();
|
||||
self.importer.miner.clear();
|
||||
let db = self.db.write();
|
||||
db.key_value().restore(new_db)?;
|
||||
db.blooms().reopen()?;
|
||||
db.trace_blooms().reopen()?;
|
||||
db.restore(new_db)?;
|
||||
|
||||
let cache_size = state_db.cache_size();
|
||||
*state_db = StateDB::new(journaldb::new(db.key_value().clone(), self.pruning, ::db::COL_STATE), cache_size);
|
||||
@ -1348,7 +1349,7 @@ impl BlockInfo for Client {
|
||||
}
|
||||
|
||||
fn code_hash(&self, address: &Address, id: BlockId) -> Option<H256> {
|
||||
self.state_at(id).and_then(|s| s.code_hash(address).ok())
|
||||
self.state_at(id).and_then(|s| s.code_hash(address).unwrap_or(None))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1485,28 +1486,34 @@ 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);
|
||||
|
||||
let mut clone = state.clone();
|
||||
Ok(Executive::new(&mut clone, &env_info, self.engine.machine())
|
||||
Executive::new(&mut clone, &env_info, self.engine.machine())
|
||||
.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)
|
||||
}
|
||||
@ -1515,12 +1522,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.into();
|
||||
trace!(target: "estimate_gas", "{} .. {} .. {}", lower, mid, upper);
|
||||
let c = cond(mid)?;
|
||||
let c = cond(mid);
|
||||
match c {
|
||||
true => upper = mid,
|
||||
false => lower = mid,
|
||||
@ -1952,7 +1959,25 @@ impl BlockChainClient for Client {
|
||||
(*self.build_last_hashes(&self.chain.read().best_block_hash())).clone()
|
||||
}
|
||||
|
||||
fn ready_transactions(&self, max_len: usize) -> Vec<Arc<VerifiedTransaction>> {
|
||||
fn transactions_to_propagate(&self) -> Vec<Arc<VerifiedTransaction>> {
|
||||
const PROPAGATE_FOR_BLOCKS: u32 = 4;
|
||||
const MIN_TX_TO_PROPAGATE: usize = 256;
|
||||
|
||||
let block_gas_limit = *self.best_block_header().gas_limit();
|
||||
let min_tx_gas: U256 = self.latest_schedule().tx_gas.into();
|
||||
|
||||
let max_len = if min_tx_gas.is_zero() {
|
||||
usize::max_value()
|
||||
} else {
|
||||
cmp::max(
|
||||
MIN_TX_TO_PROPAGATE,
|
||||
cmp::min(
|
||||
(block_gas_limit / min_tx_gas) * PROPAGATE_FOR_BLOCKS,
|
||||
// never more than usize
|
||||
usize::max_value().into()
|
||||
).as_u64() as usize
|
||||
)
|
||||
};
|
||||
self.importer.miner.ready_transactions(self, max_len, ::miner::PendingOrdering::Priority)
|
||||
}
|
||||
|
||||
@ -2001,17 +2026,13 @@ impl BlockChainClient for Client {
|
||||
fn registrar_address(&self) -> Option<Address> {
|
||||
self.registrar_address.clone()
|
||||
}
|
||||
|
||||
fn eip86_transition(&self) -> u64 {
|
||||
self.engine().params().eip86_transition
|
||||
}
|
||||
}
|
||||
|
||||
impl IoClient for Client {
|
||||
fn queue_transactions(&self, transactions: Vec<Bytes>, peer_id: usize) {
|
||||
trace_time!("queue_transactions");
|
||||
let len = transactions.len();
|
||||
self.queue_transactions.queue(&mut self.io_channel.lock(), len, move |client| {
|
||||
self.queue_transactions.queue(&self.io_channel.read(), len, move |client| {
|
||||
trace_time!("import_queued_transactions");
|
||||
|
||||
let txs: Vec<UnverifiedTransaction> = transactions
|
||||
@ -2060,7 +2081,7 @@ impl IoClient for Client {
|
||||
|
||||
let queued = self.queued_ancient_blocks.clone();
|
||||
let lock = self.ancient_blocks_import_lock.clone();
|
||||
match self.queue_ancient_blocks.queue(&mut self.io_channel.lock(), 1, move |client| {
|
||||
self.queue_ancient_blocks.queue(&self.io_channel.read(), 1, move |client| {
|
||||
trace_time!("import_ancient_block");
|
||||
// Make sure to hold the lock here to prevent importing out of order.
|
||||
// We use separate lock, cause we don't want to block queueing.
|
||||
@ -2085,14 +2106,13 @@ impl IoClient for Client {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}) {
|
||||
Ok(_) => Ok(hash),
|
||||
Err(e) => bail!(BlockImportErrorKind::Other(format!("{}", e))),
|
||||
}
|
||||
})?;
|
||||
|
||||
Ok(hash)
|
||||
}
|
||||
|
||||
fn queue_consensus_message(&self, message: Bytes) {
|
||||
match self.queue_consensus_message.queue(&mut self.io_channel.lock(), 1, move |client| {
|
||||
match self.queue_consensus_message.queue(&self.io_channel.read(), 1, move |client| {
|
||||
if let Err(e) = client.engine().handle_message(&message) {
|
||||
debug!(target: "poa", "Invalid message received: {}", e);
|
||||
}
|
||||
@ -2202,7 +2222,14 @@ impl ImportSealedBlock for Client {
|
||||
route
|
||||
};
|
||||
let route = ChainRoute::from([route].as_ref());
|
||||
self.importer.miner.chain_new_blocks(self, &[h.clone()], &[], route.enacted(), route.retracted(), self.engine.seals_internally().is_some());
|
||||
self.importer.miner.chain_new_blocks(
|
||||
self,
|
||||
&[h.clone()],
|
||||
&[],
|
||||
route.enacted(),
|
||||
route.retracted(),
|
||||
self.engine.seals_internally().is_some(),
|
||||
);
|
||||
self.notify(|notify| {
|
||||
notify.new_blocks(
|
||||
vec![h.clone()],
|
||||
@ -2290,14 +2317,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,
|
||||
)
|
||||
}
|
||||
|
||||
@ -2497,21 +2523,6 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum QueueError {
|
||||
Channel(IoError),
|
||||
Full(usize),
|
||||
}
|
||||
|
||||
impl fmt::Display for QueueError {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
QueueError::Channel(ref c) => fmt::Display::fmt(c, fmt),
|
||||
QueueError::Full(limit) => write!(fmt, "The queue is full ({})", limit),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Queue some items to be processed by IO client.
|
||||
struct IoChannelQueue {
|
||||
currently_queued: Arc<AtomicUsize>,
|
||||
@ -2526,11 +2537,11 @@ impl IoChannelQueue {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn queue<F>(&self, channel: &mut IoChannel<ClientIoMessage>, count: usize, fun: F) -> Result<(), QueueError> where
|
||||
pub fn queue<F>(&self, channel: &IoChannel<ClientIoMessage>, count: usize, fun: F) -> Result<(), QueueError> where
|
||||
F: Fn(&Client) + Send + Sync + 'static,
|
||||
{
|
||||
let queue_size = self.currently_queued.load(AtomicOrdering::Relaxed);
|
||||
ensure!(queue_size < self.limit, QueueError::Full(self.limit));
|
||||
ensure!(queue_size < self.limit, QueueErrorKind::Full(self.limit));
|
||||
|
||||
let currently_queued = self.currently_queued.clone();
|
||||
let result = channel.send(ClientIoMessage::execute(move |client| {
|
||||
@ -2543,7 +2554,7 @@ impl IoChannelQueue {
|
||||
self.currently_queued.fetch_add(count, AtomicOrdering::SeqCst);
|
||||
Ok(())
|
||||
},
|
||||
Err(e) => Err(QueueError::Channel(e)),
|
||||
Err(e) => bail!(QueueErrorKind::Channel(e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ impl fmt::Display for EvmTestError {
|
||||
}
|
||||
|
||||
use ethereum;
|
||||
use ethjson::state::test::ForkSpec;
|
||||
use ethjson::spec::ForkSpec;
|
||||
|
||||
/// Simplified, single-block EVM test client.
|
||||
pub struct EvmTestClient<'a> {
|
||||
@ -69,12 +69,12 @@ pub struct EvmTestClient<'a> {
|
||||
}
|
||||
|
||||
impl<'a> fmt::Debug for EvmTestClient<'a> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt.debug_struct("EvmTestClient")
|
||||
.field("state", &self.state)
|
||||
.field("spec", &self.spec.name)
|
||||
.finish()
|
||||
}
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt.debug_struct("EvmTestClient")
|
||||
.field("state", &self.state)
|
||||
.field("spec", &self.spec.name)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> EvmTestClient<'a> {
|
||||
@ -86,9 +86,9 @@ 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::EIP158ToByzantiumAt5 => Some(ethereum::new_transition_test()),
|
||||
ForkSpec::FrontierToHomesteadAt5 | ForkSpec::HomesteadToDaoAt5 | ForkSpec::HomesteadToEIP150At5 => None,
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -205,7 +205,7 @@ impl<'a> EvmTestClient<'a> {
|
||||
) -> TransactResult<T::Output, V::Output> {
|
||||
let initial_gas = transaction.gas;
|
||||
// Verify transaction
|
||||
let is_ok = transaction.verify_basic(true, None, env_info.number >= self.spec.engine.params().eip86_transition);
|
||||
let is_ok = transaction.verify_basic(true, None, false);
|
||||
if let Err(error) = is_ok {
|
||||
return TransactResult::Err {
|
||||
state_root: *self.state.root(),
|
||||
@ -217,9 +217,27 @@ impl<'a> EvmTestClient<'a> {
|
||||
let result = self.state.apply_with_tracing(&env_info, self.spec.engine.machine(), &transaction, tracer, vm_tracer);
|
||||
let scheme = self.spec.engine.machine().create_address_scheme(env_info.number);
|
||||
|
||||
// Touch the coinbase at the end of the test to simulate
|
||||
// miner reward.
|
||||
// Details: https://github.com/paritytech/parity-ethereum/issues/9431
|
||||
let schedule = self.spec.engine.machine().schedule(env_info.number);
|
||||
self.state.add_balance(&env_info.author, &0.into(), if schedule.no_empty {
|
||||
state::CleanupMode::NoEmpty
|
||||
} else {
|
||||
state::CleanupMode::ForceCreate
|
||||
}).ok();
|
||||
// Touching also means that we should remove the account if it's within eip161
|
||||
// conditions.
|
||||
self.state.kill_garbage(
|
||||
&vec![env_info.author].into_iter().collect(),
|
||||
schedule.kill_empty,
|
||||
&None,
|
||||
false
|
||||
).ok();
|
||||
self.state.commit().ok();
|
||||
|
||||
match result {
|
||||
Ok(result) => {
|
||||
self.state.commit().ok();
|
||||
TransactResult::Ok {
|
||||
state_root: *self.state.root(),
|
||||
gas_left: initial_gas - result.receipt.gas_used,
|
||||
|
@ -805,8 +805,8 @@ impl BlockChainClient for TestBlockChainClient {
|
||||
self.traces.read().clone()
|
||||
}
|
||||
|
||||
fn ready_transactions(&self, max_len: usize) -> Vec<Arc<VerifiedTransaction>> {
|
||||
self.miner.ready_transactions(self, max_len, miner::PendingOrdering::Priority)
|
||||
fn transactions_to_propagate(&self) -> Vec<Arc<VerifiedTransaction>> {
|
||||
self.miner.ready_transactions(self, 4096, miner::PendingOrdering::Priority)
|
||||
}
|
||||
|
||||
fn signing_chain_id(&self) -> Option<u64> { None }
|
||||
@ -845,8 +845,6 @@ impl BlockChainClient for TestBlockChainClient {
|
||||
}
|
||||
|
||||
fn registrar_address(&self) -> Option<Address> { None }
|
||||
|
||||
fn eip86_transition(&self) -> u64 { u64::max_value() }
|
||||
}
|
||||
|
||||
impl IoClient for TestBlockChainClient {
|
||||
|
@ -320,8 +320,8 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra
|
||||
/// Get last hashes starting from best block.
|
||||
fn last_hashes(&self) -> LastHashes;
|
||||
|
||||
/// List all transactions that are allowed into the next block.
|
||||
fn ready_transactions(&self, max_len: usize) -> Vec<Arc<VerifiedTransaction>>;
|
||||
/// List all ready transactions that should be propagated to other peers.
|
||||
fn transactions_to_propagate(&self) -> Vec<Arc<VerifiedTransaction>>;
|
||||
|
||||
/// Sorted list of transaction gas prices from at least last sample_size blocks.
|
||||
fn gas_price_corpus(&self, sample_size: usize) -> ::stats::Corpus<U256> {
|
||||
@ -377,9 +377,6 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra
|
||||
|
||||
/// Get the address of the registry itself.
|
||||
fn registrar_address(&self) -> Option<Address>;
|
||||
|
||||
/// Get the EIP-86 transition block number.
|
||||
fn eip86_transition(&self) -> u64;
|
||||
}
|
||||
|
||||
/// Provides `reopen_block` method
|
||||
|
@ -317,7 +317,7 @@ impl EmptyStep {
|
||||
|
||||
impl fmt::Display for EmptyStep {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
write!(f, "({}, {}, {})", self.signature, self.step, self.parent_hash)
|
||||
write!(f, "({:x}, {}, {:x})", self.signature, self.step, self.parent_hash)
|
||||
}
|
||||
}
|
||||
|
||||
@ -825,6 +825,10 @@ impl Engine<EthereumMachine> for AuthorityRound {
|
||||
|
||||
/// Additional engine-specific information for the user/developer concerning `header`.
|
||||
fn extra_info(&self, header: &Header) -> BTreeMap<String, String> {
|
||||
if header.seal().len() < header_expected_seal_fields(header, self.empty_steps_transition) {
|
||||
return BTreeMap::default();
|
||||
}
|
||||
|
||||
let step = header_step(header, self.empty_steps_transition).as_ref().map(ToString::to_string).unwrap_or("".into());
|
||||
let signature = header_signature(header, self.empty_steps_transition).as_ref().map(ToString::to_string).unwrap_or("".into());
|
||||
|
||||
@ -984,8 +988,10 @@ impl Engine<EthereumMachine> for AuthorityRound {
|
||||
self.clear_empty_steps(parent_step);
|
||||
|
||||
// report any skipped primaries between the parent block and
|
||||
// the block we're sealing
|
||||
self.report_skipped(header, step, u64::from(parent_step) as usize, &*validators, set_number);
|
||||
// the block we're sealing, unless we have empty steps enabled
|
||||
if header.number() < self.empty_steps_transition {
|
||||
self.report_skipped(header, step, u64::from(parent_step) as usize, &*validators, set_number);
|
||||
}
|
||||
|
||||
let mut fields = vec![
|
||||
encode(&step).into_vec(),
|
||||
@ -1149,9 +1155,10 @@ impl Engine<EthereumMachine> for AuthorityRound {
|
||||
|
||||
// If empty step messages are enabled we will validate the messages in the seal, missing messages are not
|
||||
// reported as there's no way to tell whether the empty step message was never sent or simply not included.
|
||||
if header.number() >= self.empty_steps_transition {
|
||||
let validate_empty_steps = || -> Result<(), Error> {
|
||||
let empty_steps_len = if header.number() >= self.empty_steps_transition {
|
||||
let validate_empty_steps = || -> Result<usize, Error> {
|
||||
let empty_steps = header_empty_steps(header)?;
|
||||
let empty_steps_len = empty_steps.len();
|
||||
for empty_step in empty_steps {
|
||||
if empty_step.step <= parent_step || empty_step.step >= step {
|
||||
Err(EngineError::InsufficientProof(
|
||||
@ -1168,16 +1175,27 @@ impl Engine<EthereumMachine> for AuthorityRound {
|
||||
format!("invalid empty step proof: {:?}", empty_step)))?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
Ok(empty_steps_len)
|
||||
};
|
||||
|
||||
if let err @ Err(_) = validate_empty_steps() {
|
||||
self.validators.report_benign(header.author(), set_number, header.number());
|
||||
return err;
|
||||
match validate_empty_steps() {
|
||||
Ok(len) => len,
|
||||
Err(err) => {
|
||||
self.validators.report_benign(header.author(), set_number, header.number());
|
||||
return Err(err);
|
||||
},
|
||||
}
|
||||
|
||||
} else {
|
||||
self.report_skipped(header, step, parent_step, &*validators, set_number);
|
||||
|
||||
0
|
||||
};
|
||||
|
||||
if header.number() >= self.validate_score_transition {
|
||||
let expected_difficulty = calculate_score(parent_step.into(), step.into(), empty_steps_len.into());
|
||||
if header.difficulty() != &expected_difficulty {
|
||||
return Err(From::from(BlockError::InvalidDifficulty(Mismatch { expected: expected_difficulty, found: header.difficulty().clone() })));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -1395,10 +1413,12 @@ impl Engine<EthereumMachine> for AuthorityRound {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::collections::BTreeMap;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering};
|
||||
use hash::keccak;
|
||||
use ethereum_types::{Address, H520, H256, U256};
|
||||
use ethkey::Signature;
|
||||
use header::Header;
|
||||
use rlp::encode;
|
||||
use block::*;
|
||||
@ -1412,7 +1432,7 @@ mod tests {
|
||||
use engines::{Seal, Engine, EngineError, EthEngine};
|
||||
use engines::validator_set::TestSet;
|
||||
use error::{Error, ErrorKind};
|
||||
use super::{AuthorityRoundParams, AuthorityRound, EmptyStep, SealedEmptyStep};
|
||||
use super::{AuthorityRoundParams, AuthorityRound, EmptyStep, SealedEmptyStep, calculate_score};
|
||||
|
||||
#[test]
|
||||
fn has_valid_metadata() {
|
||||
@ -1518,12 +1538,15 @@ mod tests {
|
||||
|
||||
let engine = Spec::new_test_round().engine;
|
||||
|
||||
let signature = tap.sign(addr, Some("0".into()), header.bare_hash()).unwrap();
|
||||
// Two validators.
|
||||
// Spec starts with step 2.
|
||||
header.set_difficulty(calculate_score(U256::from(0), U256::from(2), U256::zero()));
|
||||
let signature = tap.sign(addr, Some("0".into()), header.bare_hash()).unwrap();
|
||||
header.set_seal(vec![encode(&2usize).into_vec(), encode(&(&*signature as &[u8])).into_vec()]);
|
||||
assert!(engine.verify_block_family(&header, &parent_header).is_ok());
|
||||
assert!(engine.verify_block_external(&header).is_err());
|
||||
header.set_difficulty(calculate_score(U256::from(0), U256::from(1), U256::zero()));
|
||||
let signature = tap.sign(addr, Some("0".into()), header.bare_hash()).unwrap();
|
||||
header.set_seal(vec![encode(&1usize).into_vec(), encode(&(&*signature as &[u8])).into_vec()]);
|
||||
assert!(engine.verify_block_family(&header, &parent_header).is_ok());
|
||||
assert!(engine.verify_block_external(&header).is_ok());
|
||||
@ -1544,9 +1567,10 @@ mod tests {
|
||||
|
||||
let engine = Spec::new_test_round().engine;
|
||||
|
||||
let signature = tap.sign(addr, Some("0".into()), header.bare_hash()).unwrap();
|
||||
// Two validators.
|
||||
// Spec starts with step 2.
|
||||
header.set_difficulty(calculate_score(U256::from(0), U256::from(1), U256::zero()));
|
||||
let signature = tap.sign(addr, Some("0".into()), header.bare_hash()).unwrap();
|
||||
header.set_seal(vec![encode(&1usize).into_vec(), encode(&(&*signature as &[u8])).into_vec()]);
|
||||
assert!(engine.verify_block_family(&header, &parent_header).is_ok());
|
||||
assert!(engine.verify_block_external(&header).is_ok());
|
||||
@ -1573,8 +1597,10 @@ mod tests {
|
||||
// Two validators.
|
||||
// Spec starts with step 2.
|
||||
header.set_seal(vec![encode(&5usize).into_vec(), encode(&(&*signature as &[u8])).into_vec()]);
|
||||
header.set_difficulty(calculate_score(U256::from(4), U256::from(5), U256::zero()));
|
||||
assert!(engine.verify_block_family(&header, &parent_header).is_ok());
|
||||
header.set_seal(vec![encode(&3usize).into_vec(), encode(&(&*signature as &[u8])).into_vec()]);
|
||||
header.set_difficulty(calculate_score(U256::from(4), U256::from(3), U256::zero()));
|
||||
assert!(engine.verify_block_family(&header, &parent_header).is_err());
|
||||
}
|
||||
|
||||
@ -1608,6 +1634,7 @@ mod tests {
|
||||
parent_header.set_seal(vec![encode(&1usize).into_vec()]);
|
||||
parent_header.set_gas_limit("222222".parse::<U256>().unwrap());
|
||||
let mut header: Header = Header::default();
|
||||
header.set_difficulty(calculate_score(U256::from(1), U256::from(3), U256::zero()));
|
||||
header.set_gas_limit("222222".parse::<U256>().unwrap());
|
||||
header.set_seal(vec![encode(&3usize).into_vec()]);
|
||||
|
||||
@ -1967,16 +1994,15 @@ mod tests {
|
||||
let empty_step3 = sealed_empty_step(engine, 3, &parent_header.hash());
|
||||
|
||||
let empty_steps = vec![empty_step2, empty_step3];
|
||||
header.set_difficulty(calculate_score(U256::from(0), U256::from(4), U256::from(2)));
|
||||
let signature = tap.sign(addr1, Some("1".into()), header.bare_hash()).unwrap();
|
||||
header.set_seal(vec![
|
||||
encode(&4usize).into_vec(),
|
||||
encode(&(&*signature as &[u8])).into_vec(),
|
||||
::rlp::encode_list(&empty_steps).into_vec(),
|
||||
]);
|
||||
|
||||
assert!(match engine.verify_block_family(&header, &parent_header) {
|
||||
Ok(_) => true,
|
||||
_ => false,
|
||||
});
|
||||
assert!(engine.verify_block_family(&header, &parent_header).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -2047,4 +2073,40 @@ mod tests {
|
||||
addr1_balance + (1000 + 0).into() + (1000 + 2).into(),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extra_info_from_seal() {
|
||||
let (spec, tap, accounts) = setup_empty_steps();
|
||||
let engine = &*spec.engine;
|
||||
|
||||
let addr1 = accounts[0];
|
||||
engine.set_signer(tap.clone(), addr1, "1".into());
|
||||
|
||||
let mut header: Header = Header::default();
|
||||
let empty_step = empty_step(engine, 1, &header.parent_hash());
|
||||
let sealed_empty_step = empty_step.sealed();
|
||||
|
||||
header.set_number(2);
|
||||
header.set_seal(vec![
|
||||
encode(&2usize).to_vec(),
|
||||
encode(&H520::default()).to_vec(),
|
||||
::rlp::encode_list(&vec![sealed_empty_step]).to_vec(),
|
||||
]);
|
||||
|
||||
let info = engine.extra_info(&header);
|
||||
|
||||
let mut expected = BTreeMap::default();
|
||||
expected.insert("step".into(), "2".into());
|
||||
expected.insert("signature".into(), Signature::from(H520::default()).to_string());
|
||||
expected.insert("emptySteps".into(), format!("[{}]", empty_step));
|
||||
|
||||
assert_eq!(info, expected);
|
||||
|
||||
header.set_seal(vec![]);
|
||||
|
||||
assert_eq!(
|
||||
engine.extra_info(&header),
|
||||
BTreeMap::default(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -693,7 +693,6 @@ impl Engine<EthereumMachine> for Tendermint {
|
||||
}
|
||||
|
||||
fn stop(&self) {
|
||||
self.step_service.stop()
|
||||
}
|
||||
|
||||
fn is_proposal(&self, header: &Header) -> bool {
|
||||
|
@ -151,6 +151,24 @@ impl error::Error for BlockError {
|
||||
}
|
||||
}
|
||||
|
||||
error_chain! {
|
||||
types {
|
||||
QueueError, QueueErrorKind, QueueErrorResultExt, QueueErrorResult;
|
||||
}
|
||||
|
||||
errors {
|
||||
#[doc = "Queue is full"]
|
||||
Full(limit: usize) {
|
||||
description("Queue is full")
|
||||
display("The queue is full ({})", limit)
|
||||
}
|
||||
}
|
||||
|
||||
foreign_links {
|
||||
Channel(IoError) #[doc = "Io channel error"];
|
||||
}
|
||||
}
|
||||
|
||||
error_chain! {
|
||||
types {
|
||||
ImportError, ImportErrorKind, ImportErrorResultExt, ImportErrorResult;
|
||||
@ -184,6 +202,7 @@ error_chain! {
|
||||
|
||||
links {
|
||||
Import(ImportError, ImportErrorKind) #[doc = "Import error"];
|
||||
Queue(QueueError, QueueErrorKind) #[doc = "Io channel queue error"];
|
||||
}
|
||||
|
||||
foreign_links {
|
||||
|
@ -20,7 +20,7 @@ use std::collections::BTreeMap;
|
||||
use std::sync::Arc;
|
||||
use hash::{KECCAK_EMPTY_LIST_RLP};
|
||||
use engines::block_reward::{self, RewardKind};
|
||||
use ethash::{quick_get_difficulty, slow_hash_block_number, EthashManager, OptimizeFor};
|
||||
use ethash::{self, quick_get_difficulty, slow_hash_block_number, EthashManager, OptimizeFor};
|
||||
use ethereum_types::{H256, H64, U256, Address};
|
||||
use unexpected::{OutOfBounds, Mismatch};
|
||||
use block::*;
|
||||
@ -36,8 +36,9 @@ use machine::EthereumMachine;
|
||||
const SNAPSHOT_BLOCKS: u64 = 5000;
|
||||
/// Maximum number of blocks allowed in an ethash snapshot.
|
||||
const MAX_SNAPSHOT_BLOCKS: u64 = 30000;
|
||||
|
||||
/// Default number of blocks the difficulty bomb is delayed in EIP-{649,1234}
|
||||
const DEFAULT_EIP649_DELAY: u64 = 3_000_000;
|
||||
const DEFAULT_EIP1234_DELAY: u64 = 2_000_000;
|
||||
|
||||
/// Ethash specific seal
|
||||
#[derive(Debug, PartialEq)]
|
||||
@ -120,6 +121,12 @@ pub struct EthashParams {
|
||||
pub eip649_delay: u64,
|
||||
/// EIP-649 base reward.
|
||||
pub eip649_reward: Option<U256>,
|
||||
/// EIP-1234 transition block.
|
||||
pub eip1234_transition: u64,
|
||||
/// EIP-1234 bomb delay.
|
||||
pub eip1234_delay: u64,
|
||||
/// EIP-1234 base reward.
|
||||
pub eip1234_reward: Option<U256>,
|
||||
/// EXPIP-2 block height
|
||||
pub expip2_transition: u64,
|
||||
/// EXPIP-2 duration limit
|
||||
@ -152,6 +159,9 @@ impl From<ethjson::spec::EthashParams> for EthashParams {
|
||||
eip649_transition: p.eip649_transition.map_or(u64::max_value(), Into::into),
|
||||
eip649_delay: p.eip649_delay.map_or(DEFAULT_EIP649_DELAY, Into::into),
|
||||
eip649_reward: p.eip649_reward.map(Into::into),
|
||||
eip1234_transition: p.eip1234_transition.map_or(u64::max_value(), Into::into),
|
||||
eip1234_delay: p.eip1234_delay.map_or(DEFAULT_EIP1234_DELAY, Into::into),
|
||||
eip1234_reward: p.eip1234_reward.map(Into::into),
|
||||
expip2_transition: p.expip2_transition.map_or(u64::max_value(), Into::into),
|
||||
expip2_duration_limit: p.expip2_duration_limit.map_or(30, Into::into),
|
||||
}
|
||||
@ -233,8 +243,10 @@ impl Engine<EthereumMachine> for Arc<Ethash> {
|
||||
|
||||
let mut rewards = Vec::new();
|
||||
|
||||
// Applies EIP-649 reward.
|
||||
let reward = if number >= self.ethash_params.eip649_transition {
|
||||
// Applies EIP-{649,1234} reward, defaults to block_reward.
|
||||
let reward = if number >= self.ethash_params.eip1234_transition {
|
||||
self.ethash_params.eip1234_reward.unwrap_or(self.ethash_params.block_reward)
|
||||
} else if number >= self.ethash_params.eip649_transition {
|
||||
self.ethash_params.eip649_reward.unwrap_or(self.ethash_params.block_reward)
|
||||
} else {
|
||||
self.ethash_params.block_reward
|
||||
@ -280,11 +292,18 @@ impl Engine<EthereumMachine> for Arc<Ethash> {
|
||||
block_reward::apply_block_rewards(&rewards, block, &self.machine)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "miner-debug"))]
|
||||
fn verify_local_seal(&self, header: &Header) -> Result<(), Error> {
|
||||
self.verify_block_basic(header)
|
||||
.and_then(|_| self.verify_block_unordered(header))
|
||||
}
|
||||
|
||||
#[cfg(feature = "miner-debug")]
|
||||
fn verify_local_seal(&self, _header: &Header) -> Result<(), Error> {
|
||||
warn!("Skipping seal verification, running in miner testing mode.");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn verify_block_basic(&self, header: &Header) -> Result<(), Error> {
|
||||
// check the seal fields.
|
||||
let seal = Seal::parse_seal(header.seal())?;
|
||||
@ -295,7 +314,7 @@ impl Engine<EthereumMachine> for Arc<Ethash> {
|
||||
return Err(From::from(BlockError::DifficultyOutOfBounds(OutOfBounds { min: Some(min_difficulty), max: None, found: header.difficulty().clone() })))
|
||||
}
|
||||
|
||||
let difficulty = Ethash::boundary_to_difficulty(&H256(quick_get_difficulty(
|
||||
let difficulty = ethash::boundary_to_difficulty(&H256(quick_get_difficulty(
|
||||
&header.bare_hash().0,
|
||||
seal.nonce.low_u64(),
|
||||
&seal.mix_hash.0
|
||||
@ -317,7 +336,7 @@ impl Engine<EthereumMachine> for Arc<Ethash> {
|
||||
|
||||
let result = self.pow.compute_light(header.number() as u64, &header.bare_hash().0, seal.nonce.low_u64());
|
||||
let mix = H256(result.mix_hash);
|
||||
let difficulty = Ethash::boundary_to_difficulty(&H256(result.value));
|
||||
let difficulty = ethash::boundary_to_difficulty(&H256(result.value));
|
||||
trace!(target: "miner", "num: {num}, seed: {seed}, h: {h}, non: {non}, mix: {mix}, res: {res}",
|
||||
num = header.number() as u64,
|
||||
seed = H256(slow_hash_block_number(header.number() as u64)),
|
||||
@ -420,6 +439,9 @@ impl Ethash {
|
||||
if header.number() < self.ethash_params.bomb_defuse_transition {
|
||||
if header.number() < self.ethash_params.ecip1010_pause_transition {
|
||||
let mut number = header.number();
|
||||
if number >= self.ethash_params.eip1234_transition {
|
||||
number = number.saturating_sub(self.ethash_params.eip1234_delay);
|
||||
}
|
||||
if number >= self.ethash_params.eip649_transition {
|
||||
number = number.saturating_sub(self.ethash_params.eip649_delay);
|
||||
}
|
||||
@ -440,25 +462,6 @@ impl Ethash {
|
||||
}
|
||||
target
|
||||
}
|
||||
|
||||
/// Convert an Ethash boundary to its original difficulty. Basically just `f(x) = 2^256 / x`.
|
||||
pub fn boundary_to_difficulty(boundary: &H256) -> U256 {
|
||||
let d = U256::from(*boundary);
|
||||
if d <= U256::one() {
|
||||
U256::max_value()
|
||||
} else {
|
||||
((U256::one() << 255) / d) << 1
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert an Ethash difficulty to the target boundary. Basically just `f(x) = 2^256 / x`.
|
||||
pub fn difficulty_to_boundary(difficulty: &U256) -> H256 {
|
||||
if *difficulty <= U256::one() {
|
||||
U256::max_value().into()
|
||||
} else {
|
||||
(((U256::one() << 255) / *difficulty) << 1).into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn ecip1017_eras_block_reward(era_rounds: u64, mut reward: U256, block_number:u64) -> (u64, U256) {
|
||||
@ -522,6 +525,9 @@ mod tests {
|
||||
eip649_transition: u64::max_value(),
|
||||
eip649_delay: 3_000_000,
|
||||
eip649_reward: None,
|
||||
eip1234_transition: u64::max_value(),
|
||||
eip1234_delay: 2_000_000,
|
||||
eip1234_reward: None,
|
||||
expip2_transition: u64::max_value(),
|
||||
expip2_duration_limit: 30,
|
||||
}
|
||||
@ -759,16 +765,6 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_difficulty_to_boundary() {
|
||||
// result of f(0) is undefined, so do not assert the result
|
||||
let _ = Ethash::difficulty_to_boundary(&U256::from(0));
|
||||
assert_eq!(Ethash::difficulty_to_boundary(&U256::from(1)), H256::from(U256::max_value()));
|
||||
assert_eq!(Ethash::difficulty_to_boundary(&U256::from(2)), H256::from_str("8000000000000000000000000000000000000000000000000000000000000000").unwrap());
|
||||
assert_eq!(Ethash::difficulty_to_boundary(&U256::from(4)), H256::from_str("4000000000000000000000000000000000000000000000000000000000000000").unwrap());
|
||||
assert_eq!(Ethash::difficulty_to_boundary(&U256::from(32)), H256::from_str("0800000000000000000000000000000000000000000000000000000000000000").unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn difficulty_frontier() {
|
||||
let machine = new_homestead_test_machine();
|
||||
|
@ -41,31 +41,31 @@ fn load_machine(b: &[u8]) -> EthereumMachine {
|
||||
Spec::load_machine(b).expect("chain spec is invalid")
|
||||
}
|
||||
|
||||
/// Create a new Foundation Olympic 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 Foundation Mainnet chain spec.
|
||||
/// Create a new Foundation mainnet chain spec.
|
||||
pub fn new_foundation<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
|
||||
load(params.into(), include_bytes!("../../res/ethereum/foundation.json"))
|
||||
}
|
||||
|
||||
/// Create a new Classic Mainnet chain spec without the DAO hardfork.
|
||||
/// Create a new Classic mainnet chain spec without the DAO hardfork.
|
||||
pub fn new_classic<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
|
||||
load(params.into(), include_bytes!("../../res/ethereum/classic.json"))
|
||||
}
|
||||
|
||||
/// Create a new POA Network mainnet chain spec.
|
||||
pub fn new_poanet<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
|
||||
load(params.into(), include_bytes!("../../res/ethereum/poacore.json"))
|
||||
}
|
||||
|
||||
/// Create a new Tobalaba mainnet chain spec.
|
||||
pub fn new_tobalaba<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
|
||||
load(params.into(), include_bytes!("../../res/ethereum/tobalaba.json"))
|
||||
}
|
||||
|
||||
/// Create a new Expanse mainnet chain spec.
|
||||
pub fn new_expanse<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
|
||||
load(params.into(), include_bytes!("../../res/ethereum/expanse.json"))
|
||||
}
|
||||
|
||||
/// Create a new Tobalaba chain spec.
|
||||
pub fn new_tobalaba<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
|
||||
load(params.into(), include_bytes!("../../res/ethereum/tobalaba.json"))
|
||||
}
|
||||
|
||||
/// Create a new Musicoin mainnet chain spec.
|
||||
pub fn new_musicoin<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
|
||||
load(params.into(), include_bytes!("../../res/ethereum/musicoin.json"))
|
||||
@ -86,19 +86,29 @@ 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"))
|
||||
}
|
||||
|
||||
/// Create a new Ropsten testnet chain spec.
|
||||
pub fn new_ropsten<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
|
||||
load(params.into(), include_bytes!("../../res/ethereum/ropsten.json"))
|
||||
}
|
||||
|
||||
/// Create a new Kovan testnet chain spec.
|
||||
pub fn new_kovan<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
|
||||
load(params.into(), include_bytes!("../../res/ethereum/kovan.json"))
|
||||
}
|
||||
|
||||
/// Create a new Foundation Ropsten chain spec.
|
||||
pub fn new_ropsten<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
|
||||
load(params.into(), include_bytes!("../../res/ethereum/ropsten.json"))
|
||||
}
|
||||
|
||||
/// Create a new Morden chain spec.
|
||||
pub fn new_morden<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
|
||||
load(params.into(), include_bytes!("../../res/ethereum/morden.json"))
|
||||
/// Create a new POA Sokol testnet chain spec.
|
||||
pub fn new_sokol<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
|
||||
load(params.into(), include_bytes!("../../res/ethereum/poasokol.json"))
|
||||
}
|
||||
|
||||
// For tests
|
||||
@ -141,6 +151,9 @@ 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")) }
|
||||
|
||||
|
@ -61,10 +61,13 @@ pub fn contract_address(address_scheme: CreateContractAddress, sender: &Address,
|
||||
stream.append(nonce);
|
||||
(From::from(keccak(stream.as_raw())), None)
|
||||
},
|
||||
CreateContractAddress::FromCodeHash => {
|
||||
CreateContractAddress::FromSenderSaltAndCodeHash(salt) => {
|
||||
let code_hash = keccak(code);
|
||||
let mut buffer = [0xffu8; 20 + 32];
|
||||
&mut buffer[20..].copy_from_slice(&code_hash[..]);
|
||||
let mut buffer = [0u8; 1 + 20 + 32 + 32];
|
||||
buffer[0] = 0xff;
|
||||
&mut buffer[1..(1+20)].copy_from_slice(&sender[..]);
|
||||
&mut buffer[(1+20)..(1+20+32)].copy_from_slice(&salt[..]);
|
||||
&mut buffer[(1+20+32)..].copy_from_slice(&code_hash[..]);
|
||||
(From::from(keccak(&buffer[..])), Some(code_hash))
|
||||
},
|
||||
CreateContractAddress::FromSenderAndCodeHash => {
|
||||
@ -285,7 +288,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
let mut substate = Substate::new();
|
||||
|
||||
// NOTE: there can be no invalid transactions from this point.
|
||||
if !schedule.eip86 || !t.is_unsigned() {
|
||||
if !schedule.keep_unsigned_nonce || !t.is_unsigned() {
|
||||
self.state.inc_nonce(&sender)?;
|
||||
}
|
||||
self.state.sub_balance(&sender, &U256::from(gas_cost), &mut substate.to_cleanup_mode(&schedule))?;
|
||||
@ -320,7 +323,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
gas_price: t.gas_price,
|
||||
value: ActionValue::Transfer(t.value),
|
||||
code: self.state.code(address)?,
|
||||
code_hash: Some(self.state.code_hash(address)?),
|
||||
code_hash: self.state.code_hash(address)?,
|
||||
data: Some(t.data.clone()),
|
||||
call_type: CallType::Call,
|
||||
params_type: vm::ParamsType::Separate,
|
||||
@ -557,9 +560,9 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
let prev_bal = self.state.balance(¶ms.address)?;
|
||||
if let ActionValue::Transfer(val) = params.value {
|
||||
self.state.sub_balance(¶ms.sender, &val, &mut substate.to_cleanup_mode(&schedule))?;
|
||||
self.state.new_contract(¶ms.address, val + prev_bal, nonce_offset);
|
||||
self.state.new_contract(¶ms.address, val + prev_bal, nonce_offset)?;
|
||||
} else {
|
||||
self.state.new_contract(¶ms.address, prev_bal, nonce_offset);
|
||||
self.state.new_contract(¶ms.address, prev_bal, nonce_offset)?;
|
||||
}
|
||||
|
||||
let trace_info = tracer.prepare_trace_create(¶ms);
|
||||
@ -610,7 +613,8 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
let schedule = self.machine.schedule(self.info.number);
|
||||
|
||||
// refunds from SSTORE nonzero -> zero
|
||||
let sstore_refunds = U256::from(schedule.sstore_refund_gas) * substate.sstore_clears_count;
|
||||
assert!(substate.sstore_clears_refund >= 0, "On transaction level, sstore clears refund cannot go below zero.");
|
||||
let sstore_refunds = U256::from(substate.sstore_clears_refund as u64);
|
||||
// refunds from contract suicides
|
||||
let suicide_refunds = U256::from(schedule.suicide_refund_gas) * U256::from(substate.suicides.len());
|
||||
let refunds_bound = sstore_refunds + suicide_refunds;
|
||||
@ -1584,6 +1588,65 @@ mod tests {
|
||||
assert_eq!(state.storage_at(&contract_address, &H256::from(&U256::zero())).unwrap(), H256::from(&U256::from(0)));
|
||||
}
|
||||
|
||||
evm_test!{test_eip1283: test_eip1283_int}
|
||||
fn test_eip1283(factory: Factory) {
|
||||
let x1 = Address::from(0x1000);
|
||||
let x2 = Address::from(0x1001);
|
||||
let y1 = Address::from(0x2001);
|
||||
let y2 = Address::from(0x2002);
|
||||
let operating_address = Address::from(0);
|
||||
let k = H256::new();
|
||||
|
||||
let mut state = get_temp_state_with_factory(factory.clone());
|
||||
state.new_contract(&x1, U256::zero(), U256::from(1)).unwrap();
|
||||
state.init_code(&x1, "600160005560006000556001600055".from_hex().unwrap()).unwrap();
|
||||
state.new_contract(&x2, U256::zero(), U256::from(1)).unwrap();
|
||||
state.init_code(&x2, "600060005560016000556000600055".from_hex().unwrap()).unwrap();
|
||||
state.new_contract(&y1, U256::zero(), U256::from(1)).unwrap();
|
||||
state.init_code(&y1, "600060006000600061100062fffffff4".from_hex().unwrap()).unwrap();
|
||||
state.new_contract(&y2, U256::zero(), U256::from(1)).unwrap();
|
||||
state.init_code(&y2, "600060006000600061100162fffffff4".from_hex().unwrap()).unwrap();
|
||||
|
||||
let info = EnvInfo::default();
|
||||
let machine = ::ethereum::new_constantinople_test_machine();
|
||||
|
||||
assert_eq!(state.storage_at(&operating_address, &k).unwrap(), H256::from(U256::from(0)));
|
||||
// Test a call via top-level -> y1 -> x1
|
||||
let (FinalizationResult { gas_left, .. }, refund, gas) = {
|
||||
let gas = U256::from(0xffffffffffu64);
|
||||
let mut params = ActionParams::default();
|
||||
params.code = Some(Arc::new("6001600055600060006000600061200163fffffffff4".from_hex().unwrap()));
|
||||
params.gas = gas;
|
||||
let mut substate = Substate::new();
|
||||
let mut ex = Executive::new(&mut state, &info, &machine);
|
||||
let res = ex.call(params, &mut substate, BytesRef::Fixed(&mut []), &mut NoopTracer, &mut NoopVMTracer).unwrap();
|
||||
|
||||
(res, substate.sstore_clears_refund, gas)
|
||||
};
|
||||
let gas_used = gas - gas_left;
|
||||
// sstore: 0 -> (1) -> () -> (1 -> 0 -> 1)
|
||||
assert_eq!(gas_used, U256::from(41860));
|
||||
assert_eq!(refund, 19800);
|
||||
|
||||
assert_eq!(state.storage_at(&operating_address, &k).unwrap(), H256::from(U256::from(1)));
|
||||
// Test a call via top-level -> y2 -> x2
|
||||
let (FinalizationResult { gas_left, .. }, refund, gas) = {
|
||||
let gas = U256::from(0xffffffffffu64);
|
||||
let mut params = ActionParams::default();
|
||||
params.code = Some(Arc::new("6001600055600060006000600061200263fffffffff4".from_hex().unwrap()));
|
||||
params.gas = gas;
|
||||
let mut substate = Substate::new();
|
||||
let mut ex = Executive::new(&mut state, &info, &machine);
|
||||
let res = ex.call(params, &mut substate, BytesRef::Fixed(&mut []), &mut NoopTracer, &mut NoopVMTracer).unwrap();
|
||||
|
||||
(res, substate.sstore_clears_refund, gas)
|
||||
};
|
||||
let gas_used = gas - gas_left;
|
||||
// sstore: 1 -> (1) -> () -> (0 -> 1 -> 0)
|
||||
assert_eq!(gas_used, U256::from(11860));
|
||||
assert_eq!(refund, 19800);
|
||||
}
|
||||
|
||||
fn wasm_sample_code() -> Arc<Vec<u8>> {
|
||||
Arc::new(
|
||||
"0061736d01000000010d0360027f7f0060017f0060000002270303656e7603726574000003656e760673656e646572000103656e76066d656d6f727902010110030201020404017000000501000708010463616c6c00020901000ac10101be0102057f017e4100410028020441c0006b22043602042004412c6a41106a220041003602002004412c6a41086a22014200370200200441186a41106a22024100360200200441186a41086a220342003703002004420037022c2004410036021c20044100360218200441186a1001200020022802002202360200200120032903002205370200200441106a2002360200200441086a200537030020042004290318220537022c200420053703002004411410004100200441c0006a3602040b0b0a010041040b0410c00000"
|
||||
|
@ -111,6 +111,10 @@ impl<'a, T: 'a, V: 'a, B: 'a> Externalities<'a, T, V, B>
|
||||
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)
|
||||
}
|
||||
|
||||
fn storage_at(&self, key: &H256) -> vm::Result<H256> {
|
||||
self.state.storage_at(&self.origin_info.address, key).map_err(Into::into)
|
||||
}
|
||||
@ -163,7 +167,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
||||
gas: self.machine.params().eip210_contract_gas,
|
||||
gas_price: 0.into(),
|
||||
code: code,
|
||||
code_hash: Some(code_hash),
|
||||
code_hash: code_hash,
|
||||
data: Some(H256::from(number).to_vec()),
|
||||
call_type: CallType::Call,
|
||||
params_type: vm::ParamsType::Separate,
|
||||
@ -219,7 +223,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
||||
};
|
||||
|
||||
if !self.static_flag {
|
||||
if !self.schedule.eip86 || params.sender != UNSIGNED_SENDER {
|
||||
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
|
||||
@ -270,7 +274,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
||||
gas: *gas,
|
||||
gas_price: self.origin_info.gas_price,
|
||||
code: code,
|
||||
code_hash: Some(code_hash),
|
||||
code_hash: code_hash,
|
||||
data: Some(data.to_vec()),
|
||||
call_type: call_type,
|
||||
params_type: vm::ParamsType::Separate,
|
||||
@ -289,12 +293,16 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
||||
}
|
||||
}
|
||||
|
||||
fn extcode(&self, address: &Address) -> vm::Result<Arc<Bytes>> {
|
||||
Ok(self.state.code(address)?.unwrap_or_else(|| Arc::new(vec![])))
|
||||
fn extcode(&self, address: &Address) -> vm::Result<Option<Arc<Bytes>>> {
|
||||
Ok(self.state.code(address)?)
|
||||
}
|
||||
|
||||
fn extcodesize(&self, address: &Address) -> vm::Result<usize> {
|
||||
Ok(self.state.code_size(address)?.unwrap_or(0))
|
||||
fn extcodehash(&self, address: &Address) -> vm::Result<Option<H256>> {
|
||||
Ok(self.state.code_hash(address)?)
|
||||
}
|
||||
|
||||
fn extcodesize(&self, address: &Address) -> vm::Result<Option<usize>> {
|
||||
Ok(self.state.code_size(address)?)
|
||||
}
|
||||
|
||||
fn ret(mut self, gas: &U256, data: &ReturnData, apply_state: bool) -> vm::Result<U256>
|
||||
@ -390,8 +398,12 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
||||
self.depth
|
||||
}
|
||||
|
||||
fn inc_sstore_clears(&mut self) {
|
||||
self.substate.sstore_clears_count = self.substate.sstore_clears_count + U256::one();
|
||||
fn add_sstore_refund(&mut self, value: usize) {
|
||||
self.substate.sstore_clears_refund += value as i128;
|
||||
}
|
||||
|
||||
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 {
|
||||
@ -570,4 +582,44 @@ mod tests {
|
||||
|
||||
assert_eq!(setup.sub_state.suicides.len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_create() {
|
||||
use std::str::FromStr;
|
||||
|
||||
let mut setup = TestSetup::new();
|
||||
let state = &mut setup.state;
|
||||
let mut tracer = NoopTracer;
|
||||
let mut vm_tracer = NoopVMTracer;
|
||||
|
||||
let address = {
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
|
||||
match ext.create(&U256::max_value(), &U256::zero(), &[], CreateContractAddress::FromSenderAndNonce) {
|
||||
ContractCreateResult::Created(address, _) => address,
|
||||
_ => panic!("Test create failed; expected Created, got Failed/Reverted."),
|
||||
}
|
||||
};
|
||||
|
||||
assert_eq!(address, Address::from_str("bd770416a3345f91e4b34576cb804a576fa48eb1").unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_create2() {
|
||||
use std::str::FromStr;
|
||||
|
||||
let mut setup = TestSetup::new();
|
||||
let state = &mut setup.state;
|
||||
let mut tracer = NoopTracer;
|
||||
let mut vm_tracer = NoopVMTracer;
|
||||
|
||||
let address = {
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
|
||||
match ext.create(&U256::max_value(), &U256::zero(), &[], CreateContractAddress::FromSenderSaltAndCodeHash(H256::default())) {
|
||||
ContractCreateResult::Created(address, _) => address,
|
||||
_ => panic!("Test create failed; expected Created, got Failed/Reverted."),
|
||||
}
|
||||
};
|
||||
|
||||
assert_eq!(address, Address::from_str("e33c0c7f7df4809055c3eba6c09cfe4baf1bd9e0").unwrap());
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ use ethjson;
|
||||
use miner::Miner;
|
||||
use io::IoChannel;
|
||||
use test_helpers;
|
||||
use super::SKIP_TEST_STATE;
|
||||
|
||||
use super::HookType;
|
||||
|
||||
@ -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;
|
||||
@ -122,19 +131,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 +163,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 +183,7 @@ 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_TransitionTests_bcEIP158ToByzantium, "BlockchainTests/TransitionTests/bcEIP158ToByzantium/"}
|
||||
declare_test!{BlockchainTests_TransitionTests_bcFrontierToHomestead, "BlockchainTests/TransitionTests/bcFrontierToHomestead/"}
|
||||
|
@ -52,26 +52,62 @@ pub fn json_difficulty_test<H: FnMut(&str, HookType)>(json_data: &[u8], spec: Sp
|
||||
vec![]
|
||||
}
|
||||
|
||||
mod difficulty_test_byzantium {
|
||||
use super::json_difficulty_test;
|
||||
use json_tests::HookType;
|
||||
macro_rules! difficulty_json_test {
|
||||
( $spec:ident ) => {
|
||||
|
||||
fn do_json_test<H: FnMut(&str, HookType)>(json_data: &[u8], h: &mut H) -> Vec<String> {
|
||||
json_difficulty_test(json_data, ::ethereum::new_byzantium_test(), h)
|
||||
}
|
||||
|
||||
declare_test!{DifficultyTests_difficultyByzantium, "BasicTests/difficultyByzantium.json"}
|
||||
}
|
||||
|
||||
mod difficulty_test_foundation {
|
||||
use super::json_difficulty_test;
|
||||
use tempdir::TempDir;
|
||||
use json_tests::HookType;
|
||||
|
||||
fn do_json_test<H: FnMut(&str, HookType)>(json_data: &[u8], h: &mut H) -> Vec<String> {
|
||||
let tempdir = TempDir::new("").unwrap();
|
||||
json_difficulty_test(json_data, ::ethereum::new_foundation(&tempdir.path()), h)
|
||||
json_difficulty_test(json_data, ::ethereum::$spec(&tempdir.path()), h)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! difficulty_json_test_nopath {
|
||||
( $spec:ident ) => {
|
||||
|
||||
use super::json_difficulty_test;
|
||||
use json_tests::HookType;
|
||||
|
||||
fn do_json_test<H: FnMut(&str, HookType)>(json_data: &[u8], h: &mut H) -> Vec<String> {
|
||||
json_difficulty_test(json_data, ::ethereum::$spec(), h)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
mod difficulty_test {
|
||||
difficulty_json_test!(new_foundation);
|
||||
declare_test!{DifficultyTests_difficulty, "BasicTests/difficulty.json"}
|
||||
}
|
||||
|
||||
mod difficulty_test_byzantium {
|
||||
difficulty_json_test_nopath!(new_byzantium_test);
|
||||
declare_test!{DifficultyTests_difficultyByzantium, "BasicTests/difficultyByzantium.json"}
|
||||
}
|
||||
|
||||
mod difficulty_test_foundation {
|
||||
difficulty_json_test!(new_foundation);
|
||||
declare_test!{DifficultyTests_difficultyMainNetwork, "BasicTests/difficultyMainNetwork.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);
|
||||
declare_test!{DifficultyTests_difficultyFrontier, "BasicTests/difficultyFrontier.json"}
|
||||
}
|
||||
|
||||
mod difficulty_test_homestead {
|
||||
difficulty_json_test_nopath!(new_homestead_test);
|
||||
declare_test!{DifficultyTests_difficultyHomestead, "BasicTests/difficultyHomestead.json"}
|
||||
}
|
||||
|
||||
|
@ -111,6 +111,10 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for TestExt<'a, T, V, B>
|
||||
self.ext.storage_at(key)
|
||||
}
|
||||
|
||||
fn initial_storage_at(&self, key: &H256) -> vm::Result<H256> {
|
||||
self.ext.initial_storage_at(key)
|
||||
}
|
||||
|
||||
fn set_storage(&mut self, key: H256, value: H256) -> vm::Result<()> {
|
||||
self.ext.set_storage(key, value)
|
||||
}
|
||||
@ -165,14 +169,18 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for TestExt<'a, T, V, B>
|
||||
MessageCallResult::Success(*gas, ReturnData::empty())
|
||||
}
|
||||
|
||||
fn extcode(&self, address: &Address) -> vm::Result<Arc<Bytes>> {
|
||||
fn extcode(&self, address: &Address) -> vm::Result<Option<Arc<Bytes>>> {
|
||||
self.ext.extcode(address)
|
||||
}
|
||||
|
||||
fn extcodesize(&self, address: &Address) -> vm::Result<usize> {
|
||||
fn extcodesize(&self, address: &Address) -> vm::Result<Option<usize>> {
|
||||
self.ext.extcodesize(address)
|
||||
}
|
||||
|
||||
fn extcodehash(&self, address: &Address) -> vm::Result<Option<H256>> {
|
||||
self.ext.extcodehash(address)
|
||||
}
|
||||
|
||||
fn log(&mut self, topics: Vec<H256>, data: &[u8]) -> vm::Result<()> {
|
||||
self.ext.log(topics, data)
|
||||
}
|
||||
@ -201,8 +209,12 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for TestExt<'a, T, V, B>
|
||||
false
|
||||
}
|
||||
|
||||
fn inc_sstore_clears(&mut self) {
|
||||
self.ext.inc_sstore_clears()
|
||||
fn add_sstore_refund(&mut self, value: usize) {
|
||||
self.ext.add_sstore_refund(value)
|
||||
}
|
||||
|
||||
fn sub_sstore_refund(&mut self, value: usize) {
|
||||
self.ext.sub_sstore_refund(value)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -14,14 +14,24 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Dapps Service
|
||||
//! State tests to skip.
|
||||
|
||||
use v1::types::LocalDapp;
|
||||
use ethjson;
|
||||
|
||||
/// Dapps Server service.
|
||||
pub trait DappsService: Send + Sync + 'static {
|
||||
/// List available local dapps.
|
||||
fn list_dapps(&self) -> Vec<LocalDapp>;
|
||||
/// Refresh local dapps list
|
||||
fn refresh_local_dapps(&self) -> bool;
|
||||
#[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();
|
||||
@ -114,18 +130,24 @@ mod state_tests {
|
||||
json_chain_test(json_data, h)
|
||||
}
|
||||
|
||||
declare_test!{GeneralStateTest_stArgsZeroOneBalance, "GeneralStateTests/stArgsZeroOneBalance/"}
|
||||
declare_test!{GeneralStateTest_stAttackTest, "GeneralStateTests/stAttackTest/"}
|
||||
declare_test!{GeneralStateTest_stBadOpcodeTest, "GeneralStateTests/stBadOpcode/"}
|
||||
declare_test!{GeneralStateTest_stBugs, "GeneralStateTests/stBugs/"}
|
||||
declare_test!{GeneralStateTest_stCallCodes, "GeneralStateTests/stCallCodes/"}
|
||||
declare_test!{GeneralStateTest_stCallCreateCallCodeTest, "GeneralStateTests/stCallCreateCallCodeTest/"}
|
||||
declare_test!{GeneralStateTest_stCallDelegateCodesCallCodeHomestead, "GeneralStateTests/stCallDelegateCodesCallCodeHomestead/"}
|
||||
declare_test!{GeneralStateTest_stCallDelegateCodesHomestead, "GeneralStateTests/stCallDelegateCodesHomestead/"}
|
||||
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/"}
|
||||
@ -135,12 +157,15 @@ mod state_tests {
|
||||
declare_test!{GeneralStateTest_stMemoryTest, "GeneralStateTests/stMemoryTest/"}
|
||||
declare_test!{GeneralStateTest_stNonZeroCallsTest, "GeneralStateTests/stNonZeroCallsTest/"}
|
||||
declare_test!{GeneralStateTest_stPreCompiledContracts, "GeneralStateTests/stPreCompiledContracts/"}
|
||||
declare_test!{GeneralStateTest_stPreCompiledContracts2, "GeneralStateTests/stPreCompiledContracts2/"}
|
||||
declare_test!{heavy => GeneralStateTest_stQuadraticComplexityTest, "GeneralStateTests/stQuadraticComplexityTest/"}
|
||||
declare_test!{GeneralStateTest_stRandom, "GeneralStateTests/stRandom/"}
|
||||
declare_test!{GeneralStateTest_stRandom2, "GeneralStateTests/stRandom2/"}
|
||||
declare_test!{GeneralStateTest_stRecursiveCreate, "GeneralStateTests/stRecursiveCreate/"}
|
||||
declare_test!{GeneralStateTest_stRefundTest, "GeneralStateTests/stRefundTest/"}
|
||||
declare_test!{GeneralStateTest_stReturnDataTest, "GeneralStateTests/stReturnDataTest/"}
|
||||
declare_test!{GeneralStateTest_stRevertTest, "GeneralStateTests/stRevertTest/"}
|
||||
declare_test!{GeneralStateTest_stShift, "GeneralStateTests/stShift/"}
|
||||
declare_test!{GeneralStateTest_stSolidityTest, "GeneralStateTests/stSolidityTest/"}
|
||||
declare_test!{GeneralStateTest_stSpecialTest, "GeneralStateTests/stSpecialTest/"}
|
||||
declare_test!{GeneralStateTest_stStackTests, "GeneralStateTests/stStackTests/"}
|
||||
@ -152,4 +177,11 @@ mod state_tests {
|
||||
declare_test!{GeneralStateTest_stZeroCallsRevert, "GeneralStateTests/stZeroCallsRevert/"}
|
||||
declare_test!{GeneralStateTest_stZeroCallsTest, "GeneralStateTests/stZeroCallsTest/"}
|
||||
declare_test!{GeneralStateTest_stZeroKnowledge, "GeneralStateTests/stZeroKnowledge/"}
|
||||
|
||||
// Attempts to send a transaction that requires more than current balance:
|
||||
// Tx:
|
||||
// https://github.com/ethereum/tests/blob/726b161ba8a739691006cc1ba080672bb50a9d49/GeneralStateTests/stZeroKnowledge2/ecmul_0-3_5616_28000_96.json#L170
|
||||
// Balance:
|
||||
// https://github.com/ethereum/tests/blob/726b161ba8a739691006cc1ba080672bb50a9d49/GeneralStateTests/stZeroKnowledge2/ecmul_0-3_5616_28000_96.json#L126
|
||||
declare_test!{GeneralStateTest_stZeroKnowledge2, "GeneralStateTests/stZeroKnowledge2/"}
|
||||
}
|
||||
|
@ -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| {
|
||||
@ -41,6 +53,7 @@ pub fn run_test_path<H: FnMut(&str, HookType)>(
|
||||
os.push(".json");
|
||||
os
|
||||
}).collect();
|
||||
let extension = path.extension().and_then(|s| s.to_str());
|
||||
if path.is_dir() {
|
||||
for p in read_dir(path).unwrap().filter_map(|e| {
|
||||
let e = e.unwrap();
|
||||
@ -49,22 +62,42 @@ 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>,
|
||||
start_stop_hook: &mut H
|
||||
) {
|
||||
let mut data = Vec::new();
|
||||
let mut file = File::open(&path).expect("Error opening test file");
|
||||
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");
|
||||
let results = runner(&data, start_stop_hook);
|
||||
let empty: [String; 0] = [];
|
||||
|
@ -16,10 +16,11 @@
|
||||
|
||||
use std::path::Path;
|
||||
use super::test_common::*;
|
||||
use evm;
|
||||
use client::EvmTestClient;
|
||||
use header::Header;
|
||||
use ethjson;
|
||||
use rlp::Rlp;
|
||||
use transaction::{Action, UnverifiedTransaction, SignedTransaction};
|
||||
use transaction::UnverifiedTransaction;
|
||||
|
||||
/// Run transaction jsontests on a given folder.
|
||||
pub fn run_test_path<H: FnMut(&str, HookType)>(p: &Path, skip: &[&'static str], h: &mut H) {
|
||||
@ -31,55 +32,61 @@ pub fn run_test_file<H: FnMut(&str, HookType)>(p: &Path, h: &mut H) {
|
||||
::json_tests::test_common::run_test_file(p, do_json_test, h)
|
||||
}
|
||||
|
||||
// Block number used to run the tests.
|
||||
// Make sure that all the specified features are activated.
|
||||
const BLOCK_NUMBER: u64 = 0x6ffffffffffffe;
|
||||
|
||||
fn do_json_test<H: FnMut(&str, HookType)>(json_data: &[u8], start_stop_hook: &mut H) -> Vec<String> {
|
||||
let tests = ethjson::transaction::Test::load(json_data).unwrap();
|
||||
let mut failed = Vec::new();
|
||||
let frontier_schedule = evm::Schedule::new_frontier();
|
||||
let homestead_schedule = evm::Schedule::new_homestead();
|
||||
let byzantium_schedule = evm::Schedule::new_byzantium();
|
||||
for (name, test) in tests.into_iter() {
|
||||
start_stop_hook(&name, HookType::OnStart);
|
||||
|
||||
let mut fail_unless = |cond: bool, title: &str| if !cond { failed.push(name.clone()); println!("Transaction failed: {:?}: {:?}", name, title); };
|
||||
|
||||
let number: Option<u64> = test.block_number.map(Into::into);
|
||||
let schedule = match number {
|
||||
None => &frontier_schedule,
|
||||
Some(x) if x < 1_150_000 => &frontier_schedule,
|
||||
Some(x) if x < 3_000_000 => &homestead_schedule,
|
||||
Some(_) => &byzantium_schedule
|
||||
};
|
||||
let allow_chain_id_of_one = number.map_or(false, |n| n >= 2_675_000);
|
||||
let allow_unsigned = number.map_or(false, |n| n >= 3_000_000);
|
||||
|
||||
let rlp: Vec<u8> = test.rlp.into();
|
||||
let res = Rlp::new(&rlp)
|
||||
.as_val()
|
||||
.map_err(::error::Error::from)
|
||||
.and_then(|t: UnverifiedTransaction| {
|
||||
t.validate(schedule, schedule.have_delegate_call, allow_chain_id_of_one, allow_unsigned).map_err(Into::into)
|
||||
});
|
||||
|
||||
fail_unless(test.transaction.is_none() == res.is_err(), "Validity different");
|
||||
if let (Some(tx), Some(sender)) = (test.transaction, test.sender) {
|
||||
let t = res.unwrap();
|
||||
fail_unless(SignedTransaction::new(t.clone()).unwrap().sender() == sender.into(), "sender mismatch");
|
||||
let is_acceptable_chain_id = match t.chain_id() {
|
||||
None => true,
|
||||
Some(1) if allow_chain_id_of_one => true,
|
||||
_ => false,
|
||||
for (spec_name, result) in test.post_state {
|
||||
let spec = match EvmTestClient::spec_from_json(&spec_name) {
|
||||
Some(spec) => spec,
|
||||
None => {
|
||||
println!(" - {} | {:?} Ignoring tests because of missing spec", name, spec_name);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
fail_unless(is_acceptable_chain_id, "Network ID unacceptable");
|
||||
let data: Vec<u8> = tx.data.into();
|
||||
fail_unless(t.data == data, "data mismatch");
|
||||
fail_unless(t.gas_price == tx.gas_price.into(), "gas_price mismatch");
|
||||
fail_unless(t.nonce == tx.nonce.into(), "nonce mismatch");
|
||||
fail_unless(t.value == tx.value.into(), "value mismatch");
|
||||
let to: Option<ethjson::hash::Address> = tx.to.into();
|
||||
let to: Option<Address> = to.map(Into::into);
|
||||
match t.action {
|
||||
Action::Call(dest) => fail_unless(Some(dest) == to, "call/destination mismatch"),
|
||||
Action::Create => fail_unless(None == to, "create mismatch"),
|
||||
|
||||
let mut fail_unless = |cond: bool, title: &str| if !cond {
|
||||
failed.push(format!("{}-{:?}", name, spec_name));
|
||||
println!("Transaction failed: {:?}-{:?}: {:?}", name, spec_name, title);
|
||||
};
|
||||
|
||||
let rlp: Vec<u8> = test.rlp.clone().into();
|
||||
let res = Rlp::new(&rlp)
|
||||
.as_val()
|
||||
.map_err(::error::Error::from)
|
||||
.and_then(|t: UnverifiedTransaction| {
|
||||
let mut header: Header = Default::default();
|
||||
// Use high enough number to activate all required features.
|
||||
header.set_number(BLOCK_NUMBER);
|
||||
|
||||
let minimal = t.gas_required(&spec.engine.schedule(header.number())).into();
|
||||
if t.gas < minimal {
|
||||
return Err(::transaction::Error::InsufficientGas {
|
||||
minimal, got: t.gas,
|
||||
}.into());
|
||||
}
|
||||
spec.engine.verify_transaction_basic(&t, &header)?;
|
||||
Ok(spec.engine.verify_transaction_unordered(t, &header)?)
|
||||
});
|
||||
|
||||
match (res, result.hash, result.sender) {
|
||||
(Ok(t), Some(hash), Some(sender)) => {
|
||||
fail_unless(t.sender() == sender.into(), "sender mismatch");
|
||||
fail_unless(t.hash() == hash.into(), "hash mismatch");
|
||||
},
|
||||
(Err(_), None, None) => {},
|
||||
data => {
|
||||
fail_unless(
|
||||
false,
|
||||
&format!("Validity different: {:?}", data)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -92,13 +99,14 @@ fn do_json_test<H: FnMut(&str, HookType)>(json_data: &[u8], start_stop_hook: &mu
|
||||
failed
|
||||
}
|
||||
|
||||
declare_test!{TransactionTests_ttEip155VitaliksHomesead, "TransactionTests/ttEip155VitaliksHomesead"}
|
||||
declare_test!{TransactionTests_ttEip155VitaliksEip158, "TransactionTests/ttEip155VitaliksEip158"}
|
||||
declare_test!{TransactionTests_ttEip158, "TransactionTests/ttEip158"}
|
||||
declare_test!{TransactionTests_ttFrontier, "TransactionTests/ttFrontier"}
|
||||
declare_test!{TransactionTests_ttHomestead, "TransactionTests/ttHomestead"}
|
||||
declare_test!{TransactionTests_ttVRuleEip158, "TransactionTests/ttVRuleEip158"}
|
||||
declare_test!{TransactionTests_ttWrongRLPFrontier, "TransactionTests/ttWrongRLPFrontier"}
|
||||
declare_test!{TransactionTests_ttWrongRLPHomestead, "TransactionTests/ttWrongRLPHomestead"}
|
||||
declare_test!{TransactionTests_ttConstantinople, "TransactionTests/ttConstantinople"}
|
||||
declare_test!{TransactionTests_ttSpecConstantinople, "TransactionTests/ttSpecConstantinople"}
|
||||
declare_test!{TransactionTests_ttAddress, "TransactionTests/ttAddress"}
|
||||
declare_test!{TransactionTests_ttData, "TransactionTests/ttData"}
|
||||
declare_test!{TransactionTests_ttGasLimit, "TransactionTests/ttGasLimit"}
|
||||
declare_test!{TransactionTests_ttGasPrice, "TransactionTests/ttGasPrice"}
|
||||
declare_test!{TransactionTests_ttNonce, "TransactionTests/ttNonce"}
|
||||
declare_test!{TransactionTests_ttRSValue, "TransactionTests/ttRSValue"}
|
||||
declare_test!{TransactionTests_ttSignature, "TransactionTests/ttSignature"}
|
||||
declare_test!{TransactionTests_ttValue, "TransactionTests/ttValue"}
|
||||
declare_test!{TransactionTests_ttVValue, "TransactionTests/ttVValue"}
|
||||
declare_test!{TransactionTests_ttWrongRLP, "TransactionTests/ttWrongRLP"}
|
||||
|
||||
|
@ -140,7 +140,7 @@ impl EthereumMachine {
|
||||
gas_price: 0.into(),
|
||||
value: ActionValue::Transfer(0.into()),
|
||||
code: state.code(&contract_address)?,
|
||||
code_hash: Some(state.code_hash(&contract_address)?),
|
||||
code_hash: state.code_hash(&contract_address)?,
|
||||
data: data,
|
||||
call_type: CallType::Call,
|
||||
params_type: ParamsType::Separate,
|
||||
@ -309,12 +309,8 @@ impl EthereumMachine {
|
||||
}
|
||||
|
||||
/// Returns new contract address generation scheme at given block number.
|
||||
pub fn create_address_scheme(&self, number: BlockNumber) -> CreateContractAddress {
|
||||
if number >= self.params().eip86_transition {
|
||||
CreateContractAddress::FromCodeHash
|
||||
} else {
|
||||
CreateContractAddress::FromSenderAndNonce
|
||||
}
|
||||
pub fn create_address_scheme(&self, _number: BlockNumber) -> CreateContractAddress {
|
||||
CreateContractAddress::FromSenderAndNonce
|
||||
}
|
||||
|
||||
/// Verify a particular transaction is valid, regardless of order.
|
||||
|
@ -28,6 +28,7 @@ use ethcore_miner::pool::{self, TransactionQueue, VerifiedTransaction, QueueStat
|
||||
#[cfg(feature = "work-notify")]
|
||||
use ethcore_miner::work_notify::NotifyWork;
|
||||
use ethereum_types::{H256, U256, Address};
|
||||
use io::IoChannel;
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use rayon::prelude::*;
|
||||
use transaction::{
|
||||
@ -44,7 +45,7 @@ use block::{ClosedBlock, IsBlock, Block, SealedBlock};
|
||||
use client::{
|
||||
BlockChain, ChainInfo, CallContract, BlockProducer, SealedBlockImporter, Nonce
|
||||
};
|
||||
use client::BlockId;
|
||||
use client::{BlockId, ClientIoMessage};
|
||||
use executive::contract_address;
|
||||
use header::{Header, BlockNumber};
|
||||
use miner;
|
||||
@ -96,7 +97,7 @@ const DEFAULT_MINIMAL_GAS_PRICE: u64 = 20_000_000_000;
|
||||
/// before stopping attempts to push more transactions to the block.
|
||||
/// This is an optimization that prevents traversing the entire pool
|
||||
/// in case we have only a fraction of available block gas limit left.
|
||||
const MAX_SKIPPED_TRANSACTIONS: usize = 8;
|
||||
const MAX_SKIPPED_TRANSACTIONS: usize = 128;
|
||||
|
||||
/// Configures the behaviour of the miner.
|
||||
#[derive(Debug, PartialEq)]
|
||||
@ -211,6 +212,7 @@ pub struct Miner {
|
||||
transaction_queue: Arc<TransactionQueue>,
|
||||
engine: Arc<EthEngine>,
|
||||
accounts: Option<Arc<AccountProvider>>,
|
||||
io_channel: RwLock<Option<IoChannel<ClientIoMessage>>>,
|
||||
}
|
||||
|
||||
impl Miner {
|
||||
@ -227,7 +229,12 @@ impl Miner {
|
||||
}
|
||||
|
||||
/// Creates new instance of miner Arc.
|
||||
pub fn new(options: MinerOptions, gas_pricer: GasPricer, spec: &Spec, accounts: Option<Arc<AccountProvider>>) -> Self {
|
||||
pub fn new(
|
||||
options: MinerOptions,
|
||||
gas_pricer: GasPricer,
|
||||
spec: &Spec,
|
||||
accounts: Option<Arc<AccountProvider>>,
|
||||
) -> Self {
|
||||
let limits = options.pool_limits.clone();
|
||||
let verifier_options = options.pool_verification_options.clone();
|
||||
let tx_queue_strategy = options.tx_queue_strategy;
|
||||
@ -251,6 +258,7 @@ impl Miner {
|
||||
transaction_queue: Arc::new(TransactionQueue::new(limits, verifier_options, tx_queue_strategy)),
|
||||
accounts,
|
||||
engine: spec.engine.clone(),
|
||||
io_channel: RwLock::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
@ -270,6 +278,11 @@ impl Miner {
|
||||
}, GasPricer::new_fixed(minimal_gas_price), spec, accounts)
|
||||
}
|
||||
|
||||
/// Sets `IoChannel`
|
||||
pub fn set_io_channel(&self, io_channel: IoChannel<ClientIoMessage>) {
|
||||
*self.io_channel.write() = Some(io_channel);
|
||||
}
|
||||
|
||||
/// Clear all pending block states
|
||||
pub fn clear(&self) {
|
||||
self.sealing.lock().queue.reset();
|
||||
@ -293,14 +306,15 @@ impl Miner {
|
||||
/// Retrieves an existing pending block iff it's not older than given block number.
|
||||
///
|
||||
/// NOTE: This will not prepare a new pending block if it's not existing.
|
||||
/// See `map_pending_block` for alternative behaviour.
|
||||
fn map_existing_pending_block<F, T>(&self, f: F, latest_block_number: BlockNumber) -> Option<T> where
|
||||
F: FnOnce(&ClosedBlock) -> T,
|
||||
{
|
||||
self.sealing.lock().queue
|
||||
.peek_last_ref()
|
||||
.and_then(|b| {
|
||||
if b.block().header().number() > latest_block_number {
|
||||
// to prevent a data race between block import and updating pending block
|
||||
// we allow the number to be equal.
|
||||
if b.block().header().number() >= latest_block_number {
|
||||
Some(f(b))
|
||||
} else {
|
||||
None
|
||||
@ -339,7 +353,7 @@ impl Miner {
|
||||
// if at least one was pushed successfully, close and enqueue new ClosedBlock;
|
||||
// otherwise, leave everything alone.
|
||||
// otherwise, author a fresh block.
|
||||
let mut open_block = match sealing.queue.pop_if(|b| b.block().header().parent_hash() == &best_hash) {
|
||||
let mut open_block = match sealing.queue.get_pending_if(|b| b.block().header().parent_hash() == &best_hash) {
|
||||
Some(old_block) => {
|
||||
trace!(target: "miner", "prepare_block: Already have previous work; updating and returning");
|
||||
// add transactions to old_block
|
||||
@ -384,7 +398,7 @@ impl Miner {
|
||||
let max_transactions = if min_tx_gas.is_zero() {
|
||||
usize::max_value()
|
||||
} else {
|
||||
(*open_block.block().header().gas_limit() / min_tx_gas).as_u64() as usize
|
||||
MAX_SKIPPED_TRANSACTIONS.saturating_add(cmp::min(*open_block.block().header().gas_limit() / min_tx_gas, u64::max_value().into()).as_u64() as usize)
|
||||
};
|
||||
|
||||
let pending: Vec<Arc<_>> = self.transaction_queue.pending(
|
||||
@ -589,7 +603,7 @@ impl Miner {
|
||||
{
|
||||
let mut sealing = self.sealing.lock();
|
||||
sealing.next_mandatory_reseal = Instant::now() + self.options.reseal_max_period;
|
||||
sealing.queue.push(block.clone());
|
||||
sealing.queue.set_pending(block.clone());
|
||||
sealing.queue.use_last_ref();
|
||||
}
|
||||
|
||||
@ -651,7 +665,7 @@ impl Miner {
|
||||
);
|
||||
let is_new = original_work_hash.map_or(true, |h| h != block_hash);
|
||||
|
||||
sealing.queue.push(block);
|
||||
sealing.queue.set_pending(block);
|
||||
|
||||
#[cfg(feature = "work-notify")]
|
||||
{
|
||||
@ -1042,10 +1056,12 @@ impl miner::MinerService for Miner {
|
||||
|
||||
// refuse to seal the first block of the chain if it contains hard forks
|
||||
// which should be on by default.
|
||||
if block.block().header().number() == 1 && self.engine.params().contains_bugfix_hard_fork() {
|
||||
warn!("Your chain specification contains one or more hard forks which are required to be \
|
||||
on by default. Please remove these forks and start your chain again.");
|
||||
return;
|
||||
if block.block().header().number() == 1 {
|
||||
if let Some(name) = self.engine.params().nonzero_bugfix_hard_fork() {
|
||||
warn!("Your chain specification contains one or more hard forks which are required to be \
|
||||
on by default. Please remove these forks and start your chain again: {}.", name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
match self.engine.seals_internally() {
|
||||
@ -1058,7 +1074,7 @@ impl miner::MinerService for Miner {
|
||||
Some(false) => {
|
||||
trace!(target: "miner", "update_sealing: engine is not keen to seal internally right now");
|
||||
// anyway, save the block for later use
|
||||
self.sealing.lock().queue.push(block);
|
||||
self.sealing.lock().queue.set_pending(block);
|
||||
},
|
||||
None => {
|
||||
trace!(target: "miner", "update_sealing: engine does not seal internally, preparing work");
|
||||
@ -1176,7 +1192,32 @@ impl miner::MinerService for Miner {
|
||||
// (thanks to Ready), but culling can take significant amount of time,
|
||||
// so best to leave it after we create some work for miners to prevent increased
|
||||
// uncle rate.
|
||||
self.transaction_queue.cull(client);
|
||||
// If the io_channel is available attempt to offload culling to a separate task
|
||||
// to avoid blocking chain_new_blocks
|
||||
if let Some(ref channel) = *self.io_channel.read() {
|
||||
let queue = self.transaction_queue.clone();
|
||||
let nonce_cache = self.nonce_cache.clone();
|
||||
let engine = self.engine.clone();
|
||||
let accounts = self.accounts.clone();
|
||||
let refuse_service_transactions = self.options.refuse_service_transactions;
|
||||
|
||||
let cull = move |chain: &::client::Client| {
|
||||
let client = PoolClient::new(
|
||||
chain,
|
||||
&nonce_cache,
|
||||
&*engine,
|
||||
accounts.as_ref().map(|x| &**x),
|
||||
refuse_service_transactions,
|
||||
);
|
||||
queue.cull(client);
|
||||
};
|
||||
|
||||
if let Err(e) = channel.send(ClientIoMessage::execute(cull)) {
|
||||
warn!(target: "miner", "Error queueing cull: {:?}", e);
|
||||
}
|
||||
} else {
|
||||
self.transaction_queue.cull(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,8 +16,11 @@
|
||||
|
||||
//! Blockchain access for transaction pool.
|
||||
|
||||
use std::fmt;
|
||||
use std::collections::HashMap;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
fmt,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use ethereum_types::{H256, U256, Address};
|
||||
use ethcore_miner::pool;
|
||||
@ -37,9 +40,9 @@ use miner;
|
||||
use miner::service_transaction_checker::ServiceTransactionChecker;
|
||||
|
||||
/// Cache for state nonces.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct NonceCache {
|
||||
nonces: RwLock<HashMap<Address, U256>>,
|
||||
nonces: Arc<RwLock<HashMap<Address, U256>>>,
|
||||
limit: usize
|
||||
}
|
||||
|
||||
@ -47,7 +50,7 @@ impl NonceCache {
|
||||
/// Create new cache with a limit of `limit` entries.
|
||||
pub fn new(limit: usize) -> Self {
|
||||
NonceCache {
|
||||
nonces: RwLock::new(HashMap::with_capacity(limit / 2)),
|
||||
nonces: Arc::new(RwLock::new(HashMap::with_capacity(limit / 2))),
|
||||
limit,
|
||||
}
|
||||
}
|
||||
|
@ -22,8 +22,7 @@ use std::fmt;
|
||||
|
||||
use client::{Client, ImportSealedBlock};
|
||||
use ethereum_types::{H64, H256, clean_0x, U256};
|
||||
use ethereum::ethash::Ethash;
|
||||
use ethash::SeedHashCompute;
|
||||
use ethash::{self, SeedHashCompute};
|
||||
#[cfg(feature = "work-notify")]
|
||||
use ethcore_miner::work_notify::NotifyWork;
|
||||
#[cfg(feature = "work-notify")]
|
||||
@ -167,7 +166,7 @@ impl StratumJobDispatcher {
|
||||
/// Serializes payload for stratum service
|
||||
fn payload(&self, pow_hash: H256, difficulty: U256, number: u64) -> String {
|
||||
// TODO: move this to engine
|
||||
let target = Ethash::difficulty_to_boundary(&difficulty);
|
||||
let target = ethash::difficulty_to_boundary(&difficulty);
|
||||
let seed_hash = &self.seed_compute.lock().hash_block_number(number);
|
||||
let seed_hash = H256::from_slice(&seed_hash[..]);
|
||||
format!(
|
||||
|
@ -57,7 +57,7 @@ fn fmt_err<F: ::std::fmt::Display>(f: F) -> String {
|
||||
|
||||
/// Parameters common to ethereum-like blockchains.
|
||||
/// NOTE: when adding bugfix hard-fork parameters,
|
||||
/// add to `contains_bugfix_hard_fork`
|
||||
/// add to `nonzero_bugfix_hard_fork`
|
||||
///
|
||||
/// we define a "bugfix" hard fork as any hard fork which
|
||||
/// you would put on-by-default in a new chain.
|
||||
@ -96,8 +96,6 @@ pub struct CommonParams {
|
||||
pub validate_receipts_transition: BlockNumber,
|
||||
/// Validate transaction chain id.
|
||||
pub validate_chain_id_transition: BlockNumber,
|
||||
/// Number of first block where EIP-86 (Metropolis) rules begin.
|
||||
pub eip86_transition: BlockNumber,
|
||||
/// Number of first block where EIP-140 (Metropolis: REVERT opcode) rules begin.
|
||||
pub eip140_transition: BlockNumber,
|
||||
/// Number of first block where EIP-210 (Metropolis: BLOCKHASH changes) rules begin.
|
||||
@ -115,6 +113,12 @@ pub struct CommonParams {
|
||||
pub eip214_transition: BlockNumber,
|
||||
/// Number of first block where EIP-145 rules begin.
|
||||
pub eip145_transition: BlockNumber,
|
||||
/// Number of first block where EIP-1052 rules begin.
|
||||
pub eip1052_transition: BlockNumber,
|
||||
/// Number of first block where EIP-1283 rules begin.
|
||||
pub eip1283_transition: BlockNumber,
|
||||
/// Number of first block where EIP-1014 rules begin.
|
||||
pub eip1014_transition: BlockNumber,
|
||||
/// Number of first block where dust cleanup rules (EIP-168 and EIP169) begin.
|
||||
pub dust_protection_transition: BlockNumber,
|
||||
/// Nonce cap increase per block. Nonce cap is only checked if dust protection is enabled.
|
||||
@ -123,6 +127,10 @@ pub struct CommonParams {
|
||||
pub remove_dust_contracts: bool,
|
||||
/// Wasm activation blocknumber, if any disabled initially.
|
||||
pub wasm_activation_transition: BlockNumber,
|
||||
/// Number of first block where KIP-4 rules begin. Only has effect if Wasm is activated.
|
||||
pub kip4_transition: BlockNumber,
|
||||
/// Number of first block where KIP-6 rules begin. Only has effect if Wasm is activated.
|
||||
pub kip6_transition: BlockNumber,
|
||||
/// Gas limit bound divisor (how much gas limit can change per block)
|
||||
pub gas_limit_bound_divisor: U256,
|
||||
/// Registrar contract address.
|
||||
@ -169,11 +177,13 @@ impl CommonParams {
|
||||
|
||||
/// Apply common spec config parameters to the schedule.
|
||||
pub fn update_schedule(&self, block_number: u64, schedule: &mut ::vm::Schedule) {
|
||||
schedule.have_create2 = block_number >= self.eip86_transition;
|
||||
schedule.have_create2 = block_number >= self.eip1014_transition;
|
||||
schedule.have_revert = block_number >= self.eip140_transition;
|
||||
schedule.have_static_call = block_number >= self.eip214_transition;
|
||||
schedule.have_return_data = block_number >= self.eip211_transition;
|
||||
schedule.have_bitwise_shifting = block_number >= self.eip145_transition;
|
||||
schedule.have_extcodehash = block_number >= self.eip1052_transition;
|
||||
schedule.eip1283 = block_number >= self.eip1283_transition;
|
||||
if block_number >= self.eip210_transition {
|
||||
schedule.blockhash_gas = 800;
|
||||
}
|
||||
@ -184,17 +194,32 @@ impl CommonParams {
|
||||
};
|
||||
}
|
||||
if block_number >= self.wasm_activation_transition {
|
||||
schedule.wasm = Some(Default::default());
|
||||
let mut wasm = ::vm::WasmCosts::default();
|
||||
if block_number >= self.kip4_transition {
|
||||
wasm.have_create2 = true;
|
||||
}
|
||||
if block_number >= self.kip6_transition {
|
||||
wasm.have_gasleft = true;
|
||||
}
|
||||
schedule.wasm = Some(wasm);
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether these params contain any bug-fix hard forks.
|
||||
pub fn contains_bugfix_hard_fork(&self) -> bool {
|
||||
self.eip98_transition != 0 && self.eip155_transition != 0 &&
|
||||
self.validate_receipts_transition != 0 && self.eip86_transition != 0 &&
|
||||
self.eip140_transition != 0 && self.eip210_transition != 0 &&
|
||||
self.eip211_transition != 0 && self.eip214_transition != 0 &&
|
||||
self.validate_chain_id_transition != 0 && self.dust_protection_transition != 0
|
||||
/// Return Some if the current parameters contain a bugfix hard fork not on block 0.
|
||||
pub fn nonzero_bugfix_hard_fork(&self) -> Option<&str> {
|
||||
if self.eip155_transition != 0 {
|
||||
return Some("eip155Transition");
|
||||
}
|
||||
|
||||
if self.validate_receipts_transition != 0 {
|
||||
return Some("validateReceiptsTransition");
|
||||
}
|
||||
|
||||
if self.validate_chain_id_transition != 0 {
|
||||
return Some("validateChainIdTransition");
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
@ -224,10 +249,6 @@ impl From<ethjson::spec::Params> for CommonParams {
|
||||
eip155_transition: p.eip155_transition.map_or(0, Into::into),
|
||||
validate_receipts_transition: p.validate_receipts_transition.map_or(0, Into::into),
|
||||
validate_chain_id_transition: p.validate_chain_id_transition.map_or(0, Into::into),
|
||||
eip86_transition: p.eip86_transition.map_or_else(
|
||||
BlockNumber::max_value,
|
||||
Into::into,
|
||||
),
|
||||
eip140_transition: p.eip140_transition.map_or_else(
|
||||
BlockNumber::max_value,
|
||||
Into::into,
|
||||
@ -262,6 +283,18 @@ impl From<ethjson::spec::Params> for CommonParams {
|
||||
BlockNumber::max_value,
|
||||
Into::into,
|
||||
),
|
||||
eip1052_transition: p.eip1052_transition.map_or_else(
|
||||
BlockNumber::max_value,
|
||||
Into::into,
|
||||
),
|
||||
eip1283_transition: p.eip1283_transition.map_or_else(
|
||||
BlockNumber::max_value,
|
||||
Into::into,
|
||||
),
|
||||
eip1014_transition: p.eip1014_transition.map_or_else(
|
||||
BlockNumber::max_value,
|
||||
Into::into,
|
||||
),
|
||||
dust_protection_transition: p.dust_protection_transition.map_or_else(
|
||||
BlockNumber::max_value,
|
||||
Into::into,
|
||||
@ -279,6 +312,14 @@ impl From<ethjson::spec::Params> for CommonParams {
|
||||
BlockNumber::max_value,
|
||||
Into::into
|
||||
),
|
||||
kip4_transition: p.kip4_transition.map_or_else(
|
||||
BlockNumber::max_value,
|
||||
Into::into
|
||||
),
|
||||
kip6_transition: p.kip6_transition.map_or_else(
|
||||
BlockNumber::max_value,
|
||||
Into::into
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -821,14 +862,13 @@ impl Spec {
|
||||
data: d,
|
||||
}.fake_sign(from);
|
||||
|
||||
let res = ::state::prove_transaction(
|
||||
let res = ::state::prove_transaction_virtual(
|
||||
db.as_hashdb_mut(),
|
||||
*genesis.state_root(),
|
||||
&tx,
|
||||
self.engine.machine(),
|
||||
&env_info,
|
||||
factories.clone(),
|
||||
true,
|
||||
);
|
||||
|
||||
res.map(|(out, proof)| {
|
||||
|
@ -59,6 +59,10 @@ pub struct Account {
|
||||
// LRU Cache of the trie-backed storage.
|
||||
// This is limited to `STORAGE_CACHE_ITEMS` recent queries
|
||||
storage_cache: RefCell<LruCache<H256, H256>>,
|
||||
// LRU Cache of the trie-backed storage for original value.
|
||||
// This is only used when the initial storage root is different compared to
|
||||
// what is in the database. That is, it is only used for new contracts.
|
||||
original_storage_cache: Option<(H256, RefCell<LruCache<H256, H256>>)>,
|
||||
// Modified storage. Accumulates changes to storage made in `set_storage`
|
||||
// Takes precedence over `storage_cache`.
|
||||
storage_changes: HashMap<H256, H256>,
|
||||
@ -81,6 +85,7 @@ impl From<BasicAccount> for Account {
|
||||
nonce: basic.nonce,
|
||||
storage_root: basic.storage_root,
|
||||
storage_cache: Self::empty_storage_cache(),
|
||||
original_storage_cache: None,
|
||||
storage_changes: HashMap::new(),
|
||||
code_hash: basic.code_hash,
|
||||
code_size: None,
|
||||
@ -100,6 +105,7 @@ impl Account {
|
||||
nonce: nonce,
|
||||
storage_root: KECCAK_NULL_RLP,
|
||||
storage_cache: Self::empty_storage_cache(),
|
||||
original_storage_cache: None,
|
||||
storage_changes: storage,
|
||||
code_hash: keccak(&code),
|
||||
code_size: Some(code.len()),
|
||||
@ -120,6 +126,7 @@ impl Account {
|
||||
nonce: pod.nonce,
|
||||
storage_root: KECCAK_NULL_RLP,
|
||||
storage_cache: Self::empty_storage_cache(),
|
||||
original_storage_cache: None,
|
||||
storage_changes: pod.storage.into_iter().collect(),
|
||||
code_hash: pod.code.as_ref().map_or(KECCAK_EMPTY, |c| keccak(c)),
|
||||
code_filth: Filth::Dirty,
|
||||
@ -136,6 +143,7 @@ impl Account {
|
||||
nonce: nonce,
|
||||
storage_root: KECCAK_NULL_RLP,
|
||||
storage_cache: Self::empty_storage_cache(),
|
||||
original_storage_cache: None,
|
||||
storage_changes: HashMap::new(),
|
||||
code_hash: KECCAK_EMPTY,
|
||||
code_cache: Arc::new(vec![]),
|
||||
@ -154,12 +162,17 @@ impl Account {
|
||||
|
||||
/// Create a new contract account.
|
||||
/// NOTE: make sure you use `init_code` on this before `commit`ing.
|
||||
pub fn new_contract(balance: U256, nonce: U256) -> Account {
|
||||
pub fn new_contract(balance: U256, nonce: U256, original_storage_root: H256) -> Account {
|
||||
Account {
|
||||
balance: balance,
|
||||
nonce: nonce,
|
||||
storage_root: KECCAK_NULL_RLP,
|
||||
storage_cache: Self::empty_storage_cache(),
|
||||
original_storage_cache: if original_storage_root == KECCAK_NULL_RLP {
|
||||
None
|
||||
} else {
|
||||
Some((original_storage_root, Self::empty_storage_cache()))
|
||||
},
|
||||
storage_changes: HashMap::new(),
|
||||
code_hash: KECCAK_EMPTY,
|
||||
code_cache: Arc::new(vec![]),
|
||||
@ -204,11 +217,43 @@ impl Account {
|
||||
if let Some(value) = self.cached_storage_at(key) {
|
||||
return Ok(value);
|
||||
}
|
||||
let db = SecTrieDB::new(db, &self.storage_root)?;
|
||||
Self::get_and_cache_storage(
|
||||
&self.storage_root,
|
||||
&mut self.storage_cache.borrow_mut(),
|
||||
db,
|
||||
key)
|
||||
}
|
||||
|
||||
/// Get (and cache) the contents of the trie's storage at `key`.
|
||||
/// Does not take modified storage into account.
|
||||
pub fn original_storage_at(&self, db: &HashDB<KeccakHasher>, key: &H256) -> TrieResult<H256> {
|
||||
if let Some(value) = self.cached_original_storage_at(key) {
|
||||
return Ok(value);
|
||||
}
|
||||
match &self.original_storage_cache {
|
||||
Some((ref original_storage_root, ref original_storage_cache)) =>
|
||||
Self::get_and_cache_storage(
|
||||
original_storage_root,
|
||||
&mut original_storage_cache.borrow_mut(),
|
||||
db,
|
||||
key
|
||||
),
|
||||
None =>
|
||||
Self::get_and_cache_storage(
|
||||
&self.storage_root,
|
||||
&mut self.storage_cache.borrow_mut(),
|
||||
db,
|
||||
key
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_and_cache_storage(storage_root: &H256, storage_cache: &mut LruCache<H256, H256>, db: &HashDB<KeccakHasher>, key: &H256) -> TrieResult<H256> {
|
||||
let db = SecTrieDB::new(db, storage_root)?;
|
||||
let panicky_decoder = |bytes:&[u8]| ::rlp::decode(&bytes).expect("decoding db value failed");
|
||||
let item: U256 = db.get_with(key, panicky_decoder)?.unwrap_or_else(U256::zero);
|
||||
let value: H256 = item.into();
|
||||
self.storage_cache.borrow_mut().insert(key.clone(), value.clone());
|
||||
storage_cache.insert(key.clone(), value.clone());
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
@ -218,10 +263,38 @@ impl Account {
|
||||
if let Some(value) = self.storage_changes.get(key) {
|
||||
return Some(value.clone())
|
||||
}
|
||||
if let Some(value) = self.storage_cache.borrow_mut().get_mut(key) {
|
||||
return Some(value.clone())
|
||||
self.cached_moved_original_storage_at(key)
|
||||
}
|
||||
|
||||
/// Get cached original storage value after last state commitment. Returns `None` if the key is not in the cache.
|
||||
pub fn cached_original_storage_at(&self, key: &H256) -> Option<H256> {
|
||||
match &self.original_storage_cache {
|
||||
Some((_, ref original_storage_cache)) => {
|
||||
if let Some(value) = original_storage_cache.borrow_mut().get_mut(key) {
|
||||
Some(value.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
None => {
|
||||
self.cached_moved_original_storage_at(key)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Get cached original storage value since last contract creation on this address. Returns `None` if the key is not in the cache.
|
||||
fn cached_moved_original_storage_at(&self, key: &H256) -> Option<H256> {
|
||||
// If storage root is empty RLP, then early return zero value. Practically, this makes it so that if
|
||||
// `original_storage_cache` is used, then `storage_cache` will always remain empty.
|
||||
if self.storage_root == KECCAK_NULL_RLP {
|
||||
return Some(H256::new());
|
||||
}
|
||||
|
||||
if let Some(value) = self.storage_cache.borrow_mut().get_mut(key) {
|
||||
Some(value.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// return the balance associated with this account.
|
||||
@ -278,12 +351,13 @@ impl Account {
|
||||
!self.code_cache.is_empty() || (self.code_cache.is_empty() && self.code_hash == KECCAK_EMPTY)
|
||||
}
|
||||
|
||||
/// Provide a database to get `code_hash`. Should not be called if it is a contract without code.
|
||||
/// Provide a database to get `code_hash`. Should not be called if it is a contract without code. Returns the cached code, if successful.
|
||||
#[must_use]
|
||||
pub fn cache_code(&mut self, db: &HashDB<KeccakHasher>) -> Option<Arc<Bytes>> {
|
||||
// TODO: fill out self.code_cache;
|
||||
trace!("Account::cache_code: ic={}; self.code_hash={:?}, self.code_cache={}", self.is_cached(), self.code_hash, self.code_cache.pretty());
|
||||
|
||||
if self.is_cached() { return Some(self.code_cache.clone()) }
|
||||
if self.is_cached() { return Some(self.code_cache.clone()); }
|
||||
|
||||
match db.get(&self.code_hash) {
|
||||
Some(x) => {
|
||||
@ -298,8 +372,7 @@ impl Account {
|
||||
}
|
||||
}
|
||||
|
||||
/// Provide code to cache. For correctness, should be the correct code for the
|
||||
/// account.
|
||||
/// Provide code to cache. For correctness, should be the correct code for the account.
|
||||
pub fn cache_given_code(&mut self, code: Arc<Bytes>) {
|
||||
trace!("Account::cache_given_code: ic={}; self.code_hash={:?}, self.code_cache={}", self.is_cached(), self.code_hash, self.code_cache.pretty());
|
||||
|
||||
@ -307,7 +380,9 @@ impl Account {
|
||||
self.code_cache = code;
|
||||
}
|
||||
|
||||
/// Provide a database to get `code_size`. Should not be called if it is a contract without code.
|
||||
/// Provide a database to get `code_size`. Should not be called if it is a contract without code. Returns whether
|
||||
/// the cache succeeds.
|
||||
#[must_use]
|
||||
pub fn cache_code_size(&mut self, db: &HashDB<KeccakHasher>) -> bool {
|
||||
// TODO: fill out self.code_cache;
|
||||
trace!("Account::cache_code_size: ic={}; self.code_hash={:?}, self.code_cache={}", self.is_cached(), self.code_hash, self.code_cache.pretty());
|
||||
@ -324,7 +399,9 @@ impl Account {
|
||||
},
|
||||
}
|
||||
} else {
|
||||
false
|
||||
// If the code hash is empty hash, then the code size is zero.
|
||||
self.code_size = Some(0);
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
@ -352,7 +429,27 @@ impl Account {
|
||||
}
|
||||
|
||||
/// Return the storage root associated with this account or None if it has been altered via the overlay.
|
||||
pub fn storage_root(&self) -> Option<&H256> { if self.storage_is_clean() {Some(&self.storage_root)} else {None} }
|
||||
pub fn storage_root(&self) -> Option<H256> {
|
||||
if self.storage_is_clean() {
|
||||
Some(self.storage_root)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the original storage root of this account.
|
||||
pub fn original_storage_root(&self) -> H256 {
|
||||
if let Some((original_storage_root, _)) = self.original_storage_cache {
|
||||
original_storage_root
|
||||
} else {
|
||||
self.storage_root
|
||||
}
|
||||
}
|
||||
|
||||
/// Storage root where the account changes are based upon.
|
||||
pub fn base_storage_root(&self) -> H256 {
|
||||
self.storage_root
|
||||
}
|
||||
|
||||
/// Return the storage overlay.
|
||||
pub fn storage_changes(&self) -> &HashMap<H256, H256> { &self.storage_changes }
|
||||
@ -387,6 +484,7 @@ impl Account {
|
||||
|
||||
self.storage_cache.borrow_mut().insert(k, v);
|
||||
}
|
||||
self.original_storage_cache = None;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -424,6 +522,7 @@ impl Account {
|
||||
nonce: self.nonce.clone(),
|
||||
storage_root: self.storage_root.clone(),
|
||||
storage_cache: Self::empty_storage_cache(),
|
||||
original_storage_cache: self.original_storage_cache.as_ref().map(|(r, _)| (*r, Self::empty_storage_cache())),
|
||||
storage_changes: HashMap::new(),
|
||||
code_hash: self.code_hash.clone(),
|
||||
code_size: self.code_size.clone(),
|
||||
@ -444,6 +543,7 @@ impl Account {
|
||||
pub fn clone_all(&self) -> Account {
|
||||
let mut account = self.clone_dirty();
|
||||
account.storage_cache = self.storage_cache.clone();
|
||||
account.original_storage_cache = self.original_storage_cache.clone();
|
||||
account
|
||||
}
|
||||
|
||||
@ -453,16 +553,21 @@ impl Account {
|
||||
pub fn overwrite_with(&mut self, other: Account) {
|
||||
self.balance = other.balance;
|
||||
self.nonce = other.nonce;
|
||||
self.storage_root = other.storage_root;
|
||||
self.code_hash = other.code_hash;
|
||||
self.code_filth = other.code_filth;
|
||||
self.code_cache = other.code_cache;
|
||||
self.code_size = other.code_size;
|
||||
self.address_hash = other.address_hash;
|
||||
let mut cache = self.storage_cache.borrow_mut();
|
||||
for (k, v) in other.storage_cache.into_inner() {
|
||||
cache.insert(k, v);
|
||||
if self.storage_root == other.storage_root {
|
||||
let mut cache = self.storage_cache.borrow_mut();
|
||||
for (k, v) in other.storage_cache.into_inner() {
|
||||
cache.insert(k, v);
|
||||
}
|
||||
} else {
|
||||
self.storage_cache = other.storage_cache;
|
||||
}
|
||||
self.original_storage_cache = other.original_storage_cache;
|
||||
self.storage_root = other.storage_root;
|
||||
self.storage_changes = other.storage_changes;
|
||||
}
|
||||
}
|
||||
@ -521,7 +626,7 @@ mod tests {
|
||||
let mut db = MemoryDB::new();
|
||||
let mut db = AccountDBMut::new(&mut db, &Address::new());
|
||||
let rlp = {
|
||||
let mut a = Account::new_contract(69.into(), 0.into());
|
||||
let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP);
|
||||
a.set_storage(0x00u64.into(), 0x1234u64.into());
|
||||
a.commit_storage(&Default::default(), &mut db).unwrap();
|
||||
a.init_code(vec![]);
|
||||
@ -530,7 +635,7 @@ mod tests {
|
||||
};
|
||||
|
||||
let a = Account::from_rlp(&rlp).expect("decoding db value failed");
|
||||
assert_eq!(*a.storage_root().unwrap(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2".into());
|
||||
assert_eq!(a.storage_root().unwrap(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2".into());
|
||||
assert_eq!(a.storage_at(&db.immutable(), &0x00u64.into()).unwrap(), 0x1234u64.into());
|
||||
assert_eq!(a.storage_at(&db.immutable(), &0x01u64.into()).unwrap(), H256::default());
|
||||
}
|
||||
@ -541,7 +646,7 @@ mod tests {
|
||||
let mut db = AccountDBMut::new(&mut db, &Address::new());
|
||||
|
||||
let rlp = {
|
||||
let mut a = Account::new_contract(69.into(), 0.into());
|
||||
let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP);
|
||||
a.init_code(vec![0x55, 0x44, 0xffu8]);
|
||||
a.commit_code(&mut db);
|
||||
a.rlp()
|
||||
@ -556,18 +661,18 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn commit_storage() {
|
||||
let mut a = Account::new_contract(69.into(), 0.into());
|
||||
let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP);
|
||||
let mut db = MemoryDB::new();
|
||||
let mut db = AccountDBMut::new(&mut db, &Address::new());
|
||||
a.set_storage(0.into(), 0x1234.into());
|
||||
assert_eq!(a.storage_root(), None);
|
||||
a.commit_storage(&Default::default(), &mut db).unwrap();
|
||||
assert_eq!(*a.storage_root().unwrap(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2".into());
|
||||
assert_eq!(a.storage_root().unwrap(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2".into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn commit_remove_commit_storage() {
|
||||
let mut a = Account::new_contract(69.into(), 0.into());
|
||||
let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP);
|
||||
let mut db = MemoryDB::new();
|
||||
let mut db = AccountDBMut::new(&mut db, &Address::new());
|
||||
a.set_storage(0.into(), 0x1234.into());
|
||||
@ -576,12 +681,12 @@ mod tests {
|
||||
a.commit_storage(&Default::default(), &mut db).unwrap();
|
||||
a.set_storage(1.into(), 0.into());
|
||||
a.commit_storage(&Default::default(), &mut db).unwrap();
|
||||
assert_eq!(*a.storage_root().unwrap(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2".into());
|
||||
assert_eq!(a.storage_root().unwrap(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2".into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn commit_code() {
|
||||
let mut a = Account::new_contract(69.into(), 0.into());
|
||||
let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP);
|
||||
let mut db = MemoryDB::new();
|
||||
let mut db = AccountDBMut::new(&mut db, &Address::new());
|
||||
a.init_code(vec![0x55, 0x44, 0xffu8]);
|
||||
@ -593,7 +698,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn reset_code() {
|
||||
let mut a = Account::new_contract(69.into(), 0.into());
|
||||
let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP);
|
||||
let mut db = MemoryDB::new();
|
||||
let mut db = AccountDBMut::new(&mut db, &Address::new());
|
||||
a.init_code(vec![0x55, 0x44, 0xffu8]);
|
||||
@ -624,7 +729,7 @@ mod tests {
|
||||
assert_eq!(*a.balance(), 69u8.into());
|
||||
assert_eq!(*a.nonce(), 0u8.into());
|
||||
assert_eq!(a.code_hash(), KECCAK_EMPTY);
|
||||
assert_eq!(a.storage_root().unwrap(), &KECCAK_NULL_RLP);
|
||||
assert_eq!(a.storage_root().unwrap(), KECCAK_NULL_RLP);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -181,6 +181,8 @@ impl AccountEntry {
|
||||
Some(acc) => {
|
||||
if let Some(ref mut ours) = self.account {
|
||||
ours.overwrite_with(acc);
|
||||
} else {
|
||||
self.account = Some(acc);
|
||||
}
|
||||
},
|
||||
None => self.account = None,
|
||||
@ -222,17 +224,16 @@ pub fn check_proof(
|
||||
}
|
||||
}
|
||||
|
||||
/// Prove a transaction on the given state.
|
||||
/// Prove a `virtual` transaction on the given state.
|
||||
/// Returns `None` when the transacion could not be proved,
|
||||
/// and a proof otherwise.
|
||||
pub fn prove_transaction<H: AsHashDB<KeccakHasher> + Send + Sync>(
|
||||
pub fn prove_transaction_virtual<H: AsHashDB<KeccakHasher> + Send + Sync>(
|
||||
db: H,
|
||||
root: H256,
|
||||
transaction: &SignedTransaction,
|
||||
machine: &Machine,
|
||||
env_info: &EnvInfo,
|
||||
factories: Factories,
|
||||
virt: bool,
|
||||
) -> Option<(Bytes, Vec<DBValue>)> {
|
||||
use self::backend::Proving;
|
||||
|
||||
@ -250,7 +251,7 @@ pub fn prove_transaction<H: AsHashDB<KeccakHasher> + Send + Sync>(
|
||||
};
|
||||
|
||||
let options = TransactOptions::with_no_tracing().dont_check_nonce().save_output_from_contract();
|
||||
match state.execute(env_info, machine, transaction, options, virt) {
|
||||
match state.execute(env_info, machine, transaction, options, true) {
|
||||
Err(ExecutionError::Internal(_)) => None,
|
||||
Err(e) => {
|
||||
trace!(target: "state", "Proved call failed: {}", e);
|
||||
@ -401,9 +402,12 @@ impl<B: Backend> State<B> {
|
||||
self.factories.vm.clone()
|
||||
}
|
||||
|
||||
/// Create a recoverable checkpoint of this state.
|
||||
pub fn checkpoint(&mut self) {
|
||||
self.checkpoints.get_mut().push(HashMap::new());
|
||||
/// Create a recoverable checkpoint of this state. Return the checkpoint index.
|
||||
pub fn checkpoint(&mut self) -> usize {
|
||||
let checkpoints = self.checkpoints.get_mut();
|
||||
let index = checkpoints.len();
|
||||
checkpoints.push(HashMap::new());
|
||||
index
|
||||
}
|
||||
|
||||
/// Merge last checkpoint with previous.
|
||||
@ -494,8 +498,10 @@ impl<B: Backend> State<B> {
|
||||
|
||||
/// Create a new contract at address `contract`. If there is already an account at the address
|
||||
/// it will have its code reset, ready for `init_code()`.
|
||||
pub fn new_contract(&mut self, contract: &Address, balance: U256, nonce_offset: U256) {
|
||||
self.insert_cache(contract, AccountEntry::new_dirty(Some(Account::new_contract(balance, self.account_start_nonce + nonce_offset))));
|
||||
pub fn new_contract(&mut self, contract: &Address, balance: U256, nonce_offset: U256) -> TrieResult<()> {
|
||||
let original_storage_root = self.original_storage_root(contract)?;
|
||||
self.insert_cache(contract, AccountEntry::new_dirty(Some(Account::new_contract(balance, self.account_start_nonce + nonce_offset, original_storage_root))));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Remove an existing account.
|
||||
@ -536,11 +542,84 @@ impl<B: Backend> State<B> {
|
||||
/// Get the storage root of account `a`.
|
||||
pub fn storage_root(&self, a: &Address) -> TrieResult<Option<H256>> {
|
||||
self.ensure_cached(a, RequireCache::None, true,
|
||||
|a| a.as_ref().and_then(|account| account.storage_root().cloned()))
|
||||
|a| a.as_ref().and_then(|account| account.storage_root()))
|
||||
}
|
||||
|
||||
/// Mutate storage of account `address` so that it is `value` for `key`.
|
||||
pub fn storage_at(&self, address: &Address, key: &H256) -> TrieResult<H256> {
|
||||
/// Get the original storage root since last commit of account `a`.
|
||||
pub fn original_storage_root(&self, a: &Address) -> TrieResult<H256> {
|
||||
Ok(self.ensure_cached(a, RequireCache::None, true,
|
||||
|a| a.as_ref().map(|account| account.original_storage_root()))?
|
||||
.unwrap_or(KECCAK_NULL_RLP))
|
||||
}
|
||||
|
||||
/// Get the value of storage at a specific checkpoint.
|
||||
pub fn checkpoint_storage_at(&self, checkpoint_index: usize, address: &Address, key: &H256) -> TrieResult<Option<H256>> {
|
||||
enum ReturnKind {
|
||||
/// Use original storage at value at this address.
|
||||
OriginalAt,
|
||||
/// Use the downward checkpoint value.
|
||||
Downward,
|
||||
}
|
||||
|
||||
let (checkpoints_len, kind) = {
|
||||
let checkpoints = self.checkpoints.borrow();
|
||||
let checkpoints_len = checkpoints.len();
|
||||
let checkpoint = match checkpoints.get(checkpoint_index) {
|
||||
Some(checkpoint) => checkpoint,
|
||||
// The checkpoint was not found. Return None.
|
||||
None => return Ok(None),
|
||||
};
|
||||
|
||||
let kind = match checkpoint.get(address) {
|
||||
// The account exists at this checkpoint.
|
||||
Some(Some(AccountEntry { account: Some(ref account), .. })) => {
|
||||
if let Some(value) = account.cached_storage_at(key) {
|
||||
return Ok(Some(value));
|
||||
} else {
|
||||
// This account has checkpoint entry, but the key is not in the entry's cache. We can use
|
||||
// original_storage_at if current account's original storage root is the same as checkpoint
|
||||
// account's original storage root. Otherwise, the account must be a newly created contract.
|
||||
if account.base_storage_root() == self.original_storage_root(address)? {
|
||||
ReturnKind::OriginalAt
|
||||
} else {
|
||||
// If account base storage root is different from the original storage root since last
|
||||
// commit, then it can only be created from a new contract, where the base storage root
|
||||
// would always be empty. Note that this branch is actually never called, because
|
||||
// `cached_storage_at` handled this case.
|
||||
warn!("Trying to get an account's cached storage value, but base storage root does not equal to original storage root! Assuming the value is empty.");
|
||||
return Ok(Some(H256::new()));
|
||||
}
|
||||
}
|
||||
},
|
||||
// The account didn't exist at that point. Return empty value.
|
||||
Some(Some(AccountEntry { account: None, .. })) => return Ok(Some(H256::new())),
|
||||
// The value was not cached at that checkpoint, meaning it was not modified at all.
|
||||
Some(None) => ReturnKind::OriginalAt,
|
||||
// This key does not have a checkpoint entry.
|
||||
None => ReturnKind::Downward,
|
||||
};
|
||||
|
||||
(checkpoints_len, kind)
|
||||
};
|
||||
|
||||
match kind {
|
||||
ReturnKind::Downward => {
|
||||
if checkpoint_index >= checkpoints_len - 1 {
|
||||
Ok(Some(self.storage_at(address, key)?))
|
||||
} else {
|
||||
self.checkpoint_storage_at(checkpoint_index + 1, address, key)
|
||||
}
|
||||
},
|
||||
ReturnKind::OriginalAt => Ok(Some(self.original_storage_at(address, key)?)),
|
||||
}
|
||||
}
|
||||
|
||||
fn storage_at_inner<FCachedStorageAt, FStorageAt>(
|
||||
&self, address: &Address, key: &H256, f_cached_at: FCachedStorageAt, f_at: FStorageAt,
|
||||
) -> TrieResult<H256> where
|
||||
FCachedStorageAt: Fn(&Account, &H256) -> Option<H256>,
|
||||
FStorageAt: Fn(&Account, &HashDB<KeccakHasher>, &H256) -> TrieResult<H256>
|
||||
{
|
||||
// Storage key search and update works like this:
|
||||
// 1. If there's an entry for the account in the local cache check for the key and return it if found.
|
||||
// 2. If there's an entry for the account in the global cache check for the key or load it into that account.
|
||||
@ -553,7 +632,7 @@ impl<B: Backend> State<B> {
|
||||
if let Some(maybe_acc) = local_cache.get(address) {
|
||||
match maybe_acc.account {
|
||||
Some(ref account) => {
|
||||
if let Some(value) = account.cached_storage_at(key) {
|
||||
if let Some(value) = f_cached_at(account, key) {
|
||||
return Ok(value);
|
||||
} else {
|
||||
local_account = Some(maybe_acc);
|
||||
@ -567,7 +646,7 @@ impl<B: Backend> State<B> {
|
||||
None => Ok(H256::new()),
|
||||
Some(a) => {
|
||||
let account_db = self.factories.accountdb.readonly(self.db.as_hashdb(), a.address_hash(address));
|
||||
a.storage_at(account_db.as_hashdb(), key)
|
||||
f_at(a, account_db.as_hashdb(), key)
|
||||
}
|
||||
});
|
||||
|
||||
@ -579,7 +658,7 @@ impl<B: Backend> State<B> {
|
||||
if let Some(ref mut acc) = local_account {
|
||||
if let Some(ref account) = acc.account {
|
||||
let account_db = self.factories.accountdb.readonly(self.db.as_hashdb(), account.address_hash(address));
|
||||
return account.storage_at(account_db.as_hashdb(), key)
|
||||
return f_at(account, account_db.as_hashdb(), key)
|
||||
} else {
|
||||
return Ok(H256::new())
|
||||
}
|
||||
@ -595,12 +674,32 @@ impl<B: Backend> State<B> {
|
||||
let maybe_acc = db.get_with(address, from_rlp)?;
|
||||
let r = maybe_acc.as_ref().map_or(Ok(H256::new()), |a| {
|
||||
let account_db = self.factories.accountdb.readonly(self.db.as_hashdb(), a.address_hash(address));
|
||||
a.storage_at(account_db.as_hashdb(), key)
|
||||
f_at(a, account_db.as_hashdb(), key)
|
||||
});
|
||||
self.insert_cache(address, AccountEntry::new_clean(maybe_acc));
|
||||
r
|
||||
}
|
||||
|
||||
/// Mutate storage of account `address` so that it is `value` for `key`.
|
||||
pub fn storage_at(&self, address: &Address, key: &H256) -> TrieResult<H256> {
|
||||
self.storage_at_inner(
|
||||
address,
|
||||
key,
|
||||
|account, key| { account.cached_storage_at(key) },
|
||||
|account, db, key| { account.storage_at(db, key) },
|
||||
)
|
||||
}
|
||||
|
||||
/// Get the value of storage after last state commitment.
|
||||
pub fn original_storage_at(&self, address: &Address, key: &H256) -> TrieResult<H256> {
|
||||
self.storage_at_inner(
|
||||
address,
|
||||
key,
|
||||
|account, key| { account.cached_original_storage_at(key) },
|
||||
|account, db, key| { account.original_storage_at(db, key) },
|
||||
)
|
||||
}
|
||||
|
||||
/// Get accounts' code.
|
||||
pub fn code(&self, a: &Address) -> TrieResult<Option<Arc<Bytes>>> {
|
||||
self.ensure_cached(a, RequireCache::Code, true,
|
||||
@ -608,9 +707,9 @@ impl<B: Backend> State<B> {
|
||||
}
|
||||
|
||||
/// Get an account's code hash.
|
||||
pub fn code_hash(&self, a: &Address) -> TrieResult<H256> {
|
||||
pub fn code_hash(&self, a: &Address) -> TrieResult<Option<H256>> {
|
||||
self.ensure_cached(a, RequireCache::None, true,
|
||||
|a| a.as_ref().map_or(KECCAK_EMPTY, |a| a.code_hash()))
|
||||
|a| a.as_ref().map(|a| a.code_hash()))
|
||||
}
|
||||
|
||||
/// Get accounts' code size.
|
||||
@ -671,13 +770,13 @@ impl<B: Backend> State<B> {
|
||||
/// Initialise the code of account `a` so that it is `code`.
|
||||
/// NOTE: Account should have been created with `new_contract`.
|
||||
pub fn init_code(&mut self, a: &Address, code: Bytes) -> TrieResult<()> {
|
||||
self.require_or_from(a, true, || Account::new_contract(0.into(), self.account_start_nonce), |_|{})?.init_code(code);
|
||||
self.require_or_from(a, true, || Account::new_contract(0.into(), self.account_start_nonce, KECCAK_NULL_RLP), |_| {})?.init_code(code);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Reset the code of account `a` so that it is `code`.
|
||||
pub fn reset_code(&mut self, a: &Address, code: Bytes) -> TrieResult<()> {
|
||||
self.require_or_from(a, true, || Account::new_contract(0.into(), self.account_start_nonce), |_|{})?.reset_code(code);
|
||||
self.require_or_from(a, true, || Account::new_contract(0.into(), self.account_start_nonce, KECCAK_NULL_RLP), |_| {})?.reset_code(code);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -760,6 +859,7 @@ impl<B: Backend> State<B> {
|
||||
|
||||
/// Commits our cached account changes into the trie.
|
||||
pub fn commit(&mut self) -> Result<(), Error> {
|
||||
assert!(self.checkpoints.borrow().is_empty());
|
||||
// first, commit the sub trees.
|
||||
let mut accounts = self.cache.borrow_mut();
|
||||
for (address, ref mut a) in accounts.iter_mut().filter(|&(_, ref a)| a.is_dirty()) {
|
||||
@ -805,6 +905,7 @@ impl<B: Backend> State<B> {
|
||||
|
||||
/// Clear state cache
|
||||
pub fn clear(&mut self) {
|
||||
assert!(self.checkpoints.borrow().is_empty());
|
||||
self.cache.borrow_mut().clear();
|
||||
}
|
||||
|
||||
@ -910,31 +1011,38 @@ impl<B: Backend> State<B> {
|
||||
Ok(pod_state::diff_pod(&pod_state_pre, &pod_state_post))
|
||||
}
|
||||
|
||||
// load required account data from the databases.
|
||||
fn update_account_cache(require: RequireCache, account: &mut Account, state_db: &B, db: &HashDB<KeccakHasher>) {
|
||||
/// Load required account data from the databases. Returns whether the cache succeeds.
|
||||
#[must_use]
|
||||
fn update_account_cache(require: RequireCache, account: &mut Account, state_db: &B, db: &HashDB<KeccakHasher>) -> bool {
|
||||
if let RequireCache::None = require {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if account.is_cached() {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
// if there's already code in the global cache, always cache it localy
|
||||
let hash = account.code_hash();
|
||||
match state_db.get_cached_code(&hash) {
|
||||
Some(code) => account.cache_given_code(code),
|
||||
Some(code) => {
|
||||
account.cache_given_code(code);
|
||||
true
|
||||
},
|
||||
None => match require {
|
||||
RequireCache::None => {},
|
||||
RequireCache::None => true,
|
||||
RequireCache::Code => {
|
||||
if let Some(code) = account.cache_code(db) {
|
||||
// propagate code loaded from the database to
|
||||
// the global code cache.
|
||||
state_db.cache_code(hash, code)
|
||||
state_db.cache_code(hash, code);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
},
|
||||
RequireCache::CodeSize => {
|
||||
account.cache_code_size(db);
|
||||
account.cache_code_size(db)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -949,8 +1057,11 @@ impl<B: Backend> State<B> {
|
||||
if let Some(ref mut maybe_acc) = self.cache.borrow_mut().get_mut(a) {
|
||||
if let Some(ref mut account) = maybe_acc.account {
|
||||
let accountdb = self.factories.accountdb.readonly(self.db.as_hashdb(), account.address_hash(a));
|
||||
Self::update_account_cache(require, account, &self.db, accountdb.as_hashdb());
|
||||
return Ok(f(Some(account)));
|
||||
if Self::update_account_cache(require, account, &self.db, accountdb.as_hashdb()) {
|
||||
return Ok(f(Some(account)));
|
||||
} else {
|
||||
return Err(Box::new(TrieError::IncompleteDatabase(H256::from(a))));
|
||||
}
|
||||
}
|
||||
return Ok(f(None));
|
||||
}
|
||||
@ -958,12 +1069,14 @@ impl<B: Backend> State<B> {
|
||||
let result = self.db.get_cached(a, |mut acc| {
|
||||
if let Some(ref mut account) = acc {
|
||||
let accountdb = self.factories.accountdb.readonly(self.db.as_hashdb(), account.address_hash(a));
|
||||
Self::update_account_cache(require, account, &self.db, accountdb.as_hashdb());
|
||||
if !Self::update_account_cache(require, account, &self.db, accountdb.as_hashdb()) {
|
||||
return Err(Box::new(TrieError::IncompleteDatabase(H256::from(a))));
|
||||
}
|
||||
}
|
||||
f(acc.map(|a| &*a))
|
||||
Ok(f(acc.map(|a| &*a)))
|
||||
});
|
||||
match result {
|
||||
Some(r) => Ok(r),
|
||||
Some(r) => Ok(r?),
|
||||
None => {
|
||||
// first check if it is not in database for sure
|
||||
if check_null && self.db.is_known_null(a) { return Ok(f(None)); }
|
||||
@ -974,7 +1087,9 @@ impl<B: Backend> State<B> {
|
||||
let mut maybe_acc = db.get_with(a, from_rlp)?;
|
||||
if let Some(ref mut account) = maybe_acc.as_mut() {
|
||||
let accountdb = self.factories.accountdb.readonly(self.db.as_hashdb(), account.address_hash(a));
|
||||
Self::update_account_cache(require, account, &self.db, accountdb.as_hashdb());
|
||||
if !Self::update_account_cache(require, account, &self.db, accountdb.as_hashdb()) {
|
||||
return Err(Box::new(TrieError::IncompleteDatabase(H256::from(a))));
|
||||
}
|
||||
}
|
||||
let r = f(maybe_acc.as_ref());
|
||||
self.insert_cache(a, AccountEntry::new_clean(maybe_acc));
|
||||
@ -985,7 +1100,7 @@ impl<B: Backend> State<B> {
|
||||
|
||||
/// Pull account `a` in our cache from the trie DB. `require_code` requires that the code be cached, too.
|
||||
fn require<'a>(&'a self, a: &Address, require_code: bool) -> TrieResult<RefMut<'a, Account>> {
|
||||
self.require_or_from(a, require_code, || Account::new_basic(0u8.into(), self.account_start_nonce), |_|{})
|
||||
self.require_or_from(a, require_code, || Account::new_basic(0u8.into(), self.account_start_nonce), |_| {})
|
||||
}
|
||||
|
||||
/// Pull account `a` in our cache from the trie DB. `require_code` requires that the code be cached, too.
|
||||
@ -1125,7 +1240,7 @@ mod tests {
|
||||
use std::sync::Arc;
|
||||
use std::str::FromStr;
|
||||
use rustc_hex::FromHex;
|
||||
use hash::keccak;
|
||||
use hash::{keccak, KECCAK_NULL_RLP};
|
||||
use super::*;
|
||||
use ethkey::Secret;
|
||||
use ethereum_types::{H256, U256, Address};
|
||||
@ -1977,7 +2092,7 @@ mod tests {
|
||||
let a = Address::zero();
|
||||
let (root, db) = {
|
||||
let mut state = get_temp_state();
|
||||
state.require_or_from(&a, false, ||Account::new_contract(42.into(), 0.into()), |_|{}).unwrap();
|
||||
state.require_or_from(&a, false, || Account::new_contract(42.into(), 0.into(), KECCAK_NULL_RLP), |_|{}).unwrap();
|
||||
state.init_code(&a, vec![1, 2, 3]).unwrap();
|
||||
assert_eq!(state.code(&a).unwrap(), Some(Arc::new(vec![1u8, 2, 3])));
|
||||
state.commit().unwrap();
|
||||
@ -2181,6 +2296,180 @@ mod tests {
|
||||
assert_eq!(state.balance(&a).unwrap(), U256::from(0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn checkpoint_revert_to_get_storage_at() {
|
||||
let mut state = get_temp_state();
|
||||
let a = Address::zero();
|
||||
let k = H256::from(U256::from(0));
|
||||
|
||||
let c0 = state.checkpoint();
|
||||
let c1 = state.checkpoint();
|
||||
state.set_storage(&a, k, H256::from(U256::from(1))).unwrap();
|
||||
|
||||
assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0))));
|
||||
assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0))));
|
||||
assert_eq!(state.storage_at(&a, &k).unwrap(), H256::from(U256::from(1)));
|
||||
|
||||
state.revert_to_checkpoint(); // Revert to c1.
|
||||
assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0))));
|
||||
assert_eq!(state.storage_at(&a, &k).unwrap(), H256::from(U256::from(0)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn checkpoint_from_empty_get_storage_at() {
|
||||
let mut state = get_temp_state();
|
||||
let a = Address::zero();
|
||||
let k = H256::from(U256::from(0));
|
||||
let k2 = H256::from(U256::from(1));
|
||||
|
||||
assert_eq!(state.storage_at(&a, &k).unwrap(), H256::from(U256::from(0)));
|
||||
state.clear();
|
||||
|
||||
let c0 = state.checkpoint();
|
||||
state.new_contract(&a, U256::zero(), U256::zero()).unwrap();
|
||||
let c1 = state.checkpoint();
|
||||
state.set_storage(&a, k, H256::from(U256::from(1))).unwrap();
|
||||
let c2 = state.checkpoint();
|
||||
let c3 = state.checkpoint();
|
||||
state.set_storage(&a, k2, H256::from(U256::from(3))).unwrap();
|
||||
state.set_storage(&a, k, H256::from(U256::from(3))).unwrap();
|
||||
let c4 = state.checkpoint();
|
||||
state.set_storage(&a, k, H256::from(U256::from(4))).unwrap();
|
||||
let c5 = state.checkpoint();
|
||||
|
||||
assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0))));
|
||||
assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0))));
|
||||
assert_eq!(state.checkpoint_storage_at(c2, &a, &k).unwrap(), Some(H256::from(U256::from(1))));
|
||||
assert_eq!(state.checkpoint_storage_at(c3, &a, &k).unwrap(), Some(H256::from(U256::from(1))));
|
||||
assert_eq!(state.checkpoint_storage_at(c4, &a, &k).unwrap(), Some(H256::from(U256::from(3))));
|
||||
assert_eq!(state.checkpoint_storage_at(c5, &a, &k).unwrap(), Some(H256::from(U256::from(4))));
|
||||
|
||||
state.discard_checkpoint(); // Commit/discard c5.
|
||||
assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0))));
|
||||
assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0))));
|
||||
assert_eq!(state.checkpoint_storage_at(c2, &a, &k).unwrap(), Some(H256::from(U256::from(1))));
|
||||
assert_eq!(state.checkpoint_storage_at(c3, &a, &k).unwrap(), Some(H256::from(U256::from(1))));
|
||||
assert_eq!(state.checkpoint_storage_at(c4, &a, &k).unwrap(), Some(H256::from(U256::from(3))));
|
||||
|
||||
state.revert_to_checkpoint(); // Revert to c4.
|
||||
assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0))));
|
||||
assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0))));
|
||||
assert_eq!(state.checkpoint_storage_at(c2, &a, &k).unwrap(), Some(H256::from(U256::from(1))));
|
||||
assert_eq!(state.checkpoint_storage_at(c3, &a, &k).unwrap(), Some(H256::from(U256::from(1))));
|
||||
|
||||
state.discard_checkpoint(); // Commit/discard c3.
|
||||
assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0))));
|
||||
assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0))));
|
||||
assert_eq!(state.checkpoint_storage_at(c2, &a, &k).unwrap(), Some(H256::from(U256::from(1))));
|
||||
|
||||
state.revert_to_checkpoint(); // Revert to c2.
|
||||
assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0))));
|
||||
assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0))));
|
||||
|
||||
state.discard_checkpoint(); // Commit/discard c1.
|
||||
assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn checkpoint_get_storage_at() {
|
||||
let mut state = get_temp_state();
|
||||
let a = Address::zero();
|
||||
let k = H256::from(U256::from(0));
|
||||
let k2 = H256::from(U256::from(1));
|
||||
|
||||
state.set_storage(&a, k, H256::from(U256::from(0xffff))).unwrap();
|
||||
state.commit().unwrap();
|
||||
state.clear();
|
||||
|
||||
assert_eq!(state.storage_at(&a, &k).unwrap(), H256::from(U256::from(0xffff)));
|
||||
state.clear();
|
||||
|
||||
let cm1 = state.checkpoint();
|
||||
let c0 = state.checkpoint();
|
||||
state.new_contract(&a, U256::zero(), U256::zero()).unwrap();
|
||||
let c1 = state.checkpoint();
|
||||
state.set_storage(&a, k, H256::from(U256::from(1))).unwrap();
|
||||
let c2 = state.checkpoint();
|
||||
let c3 = state.checkpoint();
|
||||
state.set_storage(&a, k2, H256::from(U256::from(3))).unwrap();
|
||||
state.set_storage(&a, k, H256::from(U256::from(3))).unwrap();
|
||||
let c4 = state.checkpoint();
|
||||
state.set_storage(&a, k, H256::from(U256::from(4))).unwrap();
|
||||
let c5 = state.checkpoint();
|
||||
|
||||
assert_eq!(state.checkpoint_storage_at(cm1, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff))));
|
||||
assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff))));
|
||||
assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0))));
|
||||
assert_eq!(state.checkpoint_storage_at(c2, &a, &k).unwrap(), Some(H256::from(U256::from(1))));
|
||||
assert_eq!(state.checkpoint_storage_at(c3, &a, &k).unwrap(), Some(H256::from(U256::from(1))));
|
||||
assert_eq!(state.checkpoint_storage_at(c4, &a, &k).unwrap(), Some(H256::from(U256::from(3))));
|
||||
assert_eq!(state.checkpoint_storage_at(c5, &a, &k).unwrap(), Some(H256::from(U256::from(4))));
|
||||
|
||||
state.discard_checkpoint(); // Commit/discard c5.
|
||||
assert_eq!(state.checkpoint_storage_at(cm1, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff))));
|
||||
assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff))));
|
||||
assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0))));
|
||||
assert_eq!(state.checkpoint_storage_at(c2, &a, &k).unwrap(), Some(H256::from(U256::from(1))));
|
||||
assert_eq!(state.checkpoint_storage_at(c3, &a, &k).unwrap(), Some(H256::from(U256::from(1))));
|
||||
assert_eq!(state.checkpoint_storage_at(c4, &a, &k).unwrap(), Some(H256::from(U256::from(3))));
|
||||
|
||||
state.revert_to_checkpoint(); // Revert to c4.
|
||||
assert_eq!(state.checkpoint_storage_at(cm1, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff))));
|
||||
assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff))));
|
||||
assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0))));
|
||||
assert_eq!(state.checkpoint_storage_at(c2, &a, &k).unwrap(), Some(H256::from(U256::from(1))));
|
||||
assert_eq!(state.checkpoint_storage_at(c3, &a, &k).unwrap(), Some(H256::from(U256::from(1))));
|
||||
|
||||
state.discard_checkpoint(); // Commit/discard c3.
|
||||
assert_eq!(state.checkpoint_storage_at(cm1, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff))));
|
||||
assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff))));
|
||||
assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0))));
|
||||
assert_eq!(state.checkpoint_storage_at(c2, &a, &k).unwrap(), Some(H256::from(U256::from(1))));
|
||||
|
||||
state.revert_to_checkpoint(); // Revert to c2.
|
||||
assert_eq!(state.checkpoint_storage_at(cm1, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff))));
|
||||
assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff))));
|
||||
assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0))));
|
||||
|
||||
state.discard_checkpoint(); // Commit/discard c1.
|
||||
assert_eq!(state.checkpoint_storage_at(cm1, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff))));
|
||||
assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn kill_account_with_checkpoints() {
|
||||
let mut state = get_temp_state();
|
||||
let a = Address::zero();
|
||||
let k = H256::from(U256::from(0));
|
||||
state.checkpoint();
|
||||
state.set_storage(&a, k, H256::from(U256::from(1))).unwrap();
|
||||
state.checkpoint();
|
||||
state.kill_account(&a);
|
||||
|
||||
assert_eq!(state.storage_at(&a, &k).unwrap(), H256::from(U256::from(0)));
|
||||
state.revert_to_checkpoint();
|
||||
assert_eq!(state.storage_at(&a, &k).unwrap(), H256::from(U256::from(1)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create_contract_fail() {
|
||||
let mut state = get_temp_state();
|
||||
let orig_root = state.root().clone();
|
||||
let a: Address = 1000.into();
|
||||
|
||||
state.checkpoint(); // c1
|
||||
state.new_contract(&a, U256::zero(), U256::zero()).unwrap();
|
||||
state.add_balance(&a, &U256::from(1), CleanupMode::ForceCreate).unwrap();
|
||||
state.checkpoint(); // c2
|
||||
state.add_balance(&a, &U256::from(1), CleanupMode::ForceCreate).unwrap();
|
||||
state.discard_checkpoint(); // discard c2
|
||||
state.revert_to_checkpoint(); // revert to c1
|
||||
assert_eq!(state.exists(&a).unwrap(), false);
|
||||
|
||||
state.commit().unwrap();
|
||||
assert_eq!(orig_root, state.root().clone());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create_empty() {
|
||||
let mut state = get_temp_state();
|
||||
@ -2218,7 +2507,7 @@ mod tests {
|
||||
state.add_balance(&b, &100.into(), CleanupMode::ForceCreate).unwrap(); // create a dust account
|
||||
state.add_balance(&c, &101.into(), CleanupMode::ForceCreate).unwrap(); // create a normal account
|
||||
state.add_balance(&d, &99.into(), CleanupMode::ForceCreate).unwrap(); // create another dust account
|
||||
state.new_contract(&e, 100.into(), 1.into()); // create a contract account
|
||||
state.new_contract(&e, 100.into(), 1.into()).unwrap(); // create a contract account
|
||||
state.init_code(&e, vec![0x00]).unwrap();
|
||||
state.commit().unwrap();
|
||||
state.drop()
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
//! Execution environment substate.
|
||||
use std::collections::HashSet;
|
||||
use ethereum_types::{U256, Address};
|
||||
use ethereum_types::Address;
|
||||
use log_entry::LogEntry;
|
||||
use evm::{Schedule, CleanDustMode};
|
||||
use super::CleanupMode;
|
||||
@ -34,8 +34,8 @@ pub struct Substate {
|
||||
/// Any logs.
|
||||
pub logs: Vec<LogEntry>,
|
||||
|
||||
/// Refund counter of SSTORE nonzero -> zero.
|
||||
pub sstore_clears_count: U256,
|
||||
/// Refund counter of SSTORE.
|
||||
pub sstore_clears_refund: i128,
|
||||
|
||||
/// Created contracts.
|
||||
pub contracts_created: Vec<Address>,
|
||||
@ -52,7 +52,7 @@ impl Substate {
|
||||
self.suicides.extend(s.suicides);
|
||||
self.touched.extend(s.touched);
|
||||
self.logs.extend(s.logs);
|
||||
self.sstore_clears_count = self.sstore_clears_count + s.sstore_clears_count;
|
||||
self.sstore_clears_refund += s.sstore_clears_refund;
|
||||
self.contracts_created.extend(s.contracts_created);
|
||||
}
|
||||
|
||||
@ -86,7 +86,7 @@ mod tests {
|
||||
topics: vec![],
|
||||
data: vec![]
|
||||
});
|
||||
sub_state.sstore_clears_count = 5.into();
|
||||
sub_state.sstore_clears_refund = (15000 * 5).into();
|
||||
sub_state.suicides.insert(10u64.into());
|
||||
|
||||
let mut sub_state_2 = Substate::new();
|
||||
@ -96,11 +96,11 @@ mod tests {
|
||||
topics: vec![],
|
||||
data: vec![]
|
||||
});
|
||||
sub_state_2.sstore_clears_count = 7.into();
|
||||
sub_state_2.sstore_clears_refund = (15000 * 7).into();
|
||||
|
||||
sub_state.accrue(sub_state_2);
|
||||
assert_eq!(sub_state.contracts_created.len(), 2);
|
||||
assert_eq!(sub_state.sstore_clears_count, 12.into());
|
||||
assert_eq!(sub_state.sstore_clears_refund, (15000 * 12).into());
|
||||
assert_eq!(sub_state.suicides.len(), 1);
|
||||
}
|
||||
}
|
||||
|
@ -334,11 +334,11 @@ fn does_not_propagate_delayed_transactions() {
|
||||
|
||||
client.miner().import_own_transaction(&*client, tx0).unwrap();
|
||||
client.miner().import_own_transaction(&*client, tx1).unwrap();
|
||||
assert_eq!(0, client.ready_transactions(10).len());
|
||||
assert_eq!(0, client.transactions_to_propagate().len());
|
||||
assert_eq!(0, client.miner().ready_transactions(&*client, 10, PendingOrdering::Priority).len());
|
||||
push_blocks_to_client(&client, 53, 2, 2);
|
||||
client.flush_queue();
|
||||
assert_eq!(2, client.ready_transactions(10).len());
|
||||
assert_eq!(2, client.transactions_to_propagate().len());
|
||||
assert_eq!(2, client.miner().ready_transactions(&*client, 10, PendingOrdering::Priority).len());
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ fn test_blockhash_eip210(factory: Factory) {
|
||||
let test_blockhash_contract = "73fffffffffffffffffffffffffffffffffffffffe33141561007a57600143036020526000356101006020510755600061010060205107141561005057600035610100610100602051050761010001555b6000620100006020510714156100755760003561010062010000602051050761020001555b61014a565b4360003512151561009057600060405260206040f35b610100600035430312156100b357610100600035075460605260206060f3610149565b62010000600035430312156100d157600061010060003507146100d4565b60005b156100f6576101006101006000350507610100015460805260206080f3610148565b630100000060003543031215610116576000620100006000350714610119565b60005b1561013c57610100620100006000350507610200015460a052602060a0f3610147565b600060c052602060c0f35b5b5b5b5b";
|
||||
let blockhash_contract_code = Arc::new(test_blockhash_contract.from_hex().unwrap());
|
||||
let blockhash_contract_code_hash = keccak(blockhash_contract_code.as_ref());
|
||||
let machine = ::ethereum::new_constantinople_test_machine();
|
||||
let machine = ::ethereum::new_eip210_test_machine();
|
||||
let mut env_info = EnvInfo::default();
|
||||
|
||||
// populate state with 256 last hashes
|
||||
|
@ -8,6 +8,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
[lib]
|
||||
|
||||
[dependencies]
|
||||
common-types = { path = "../types" }
|
||||
parity-bytes = { git = "https://github.com/paritytech/parity-common" }
|
||||
ethcore-network = { path = "../../util/network" }
|
||||
ethcore-network-devp2p = { path = "../../util/network-devp2p" }
|
||||
|
@ -24,6 +24,8 @@ use devp2p::NetworkService;
|
||||
use network::{NetworkProtocolHandler, NetworkContext, PeerId, ProtocolId,
|
||||
NetworkConfiguration as BasicNetworkConfiguration, NonReservedPeerMode, Error, ErrorKind,
|
||||
ConnectionFilter};
|
||||
|
||||
use types::pruning_info::PruningInfo;
|
||||
use ethereum_types::{H256, H512, U256};
|
||||
use io::{TimerToken};
|
||||
use ethcore::ethstore::ethkey::Secret;
|
||||
@ -39,7 +41,10 @@ use chain::{ETH_PROTOCOL_VERSION_63, ETH_PROTOCOL_VERSION_62,
|
||||
PAR_PROTOCOL_VERSION_1, PAR_PROTOCOL_VERSION_2, PAR_PROTOCOL_VERSION_3};
|
||||
use light::client::AsLightClient;
|
||||
use light::Provider;
|
||||
use light::net::{self as light_net, LightProtocol, Params as LightParams, Capabilities, Handler as LightHandler, EventContext};
|
||||
use light::net::{
|
||||
self as light_net, LightProtocol, Params as LightParams,
|
||||
Capabilities, Handler as LightHandler, EventContext, SampleStore,
|
||||
};
|
||||
use network::IpFilter;
|
||||
use private_tx::PrivateTxHandler;
|
||||
use transaction::UnverifiedTransaction;
|
||||
@ -256,11 +261,35 @@ pub struct EthSync {
|
||||
light_subprotocol_name: [u8; 3],
|
||||
}
|
||||
|
||||
fn light_params(
|
||||
network_id: u64,
|
||||
max_peers: u32,
|
||||
pruning_info: PruningInfo,
|
||||
sample_store: Option<Box<SampleStore>>,
|
||||
) -> LightParams {
|
||||
const MAX_LIGHTSERV_LOAD: f64 = 0.5;
|
||||
|
||||
let mut light_params = LightParams {
|
||||
network_id: network_id,
|
||||
config: Default::default(),
|
||||
capabilities: Capabilities {
|
||||
serve_headers: true,
|
||||
serve_chain_since: Some(pruning_info.earliest_chain),
|
||||
serve_state_since: Some(pruning_info.earliest_state),
|
||||
tx_relay: true,
|
||||
},
|
||||
sample_store: sample_store,
|
||||
};
|
||||
|
||||
let max_peers = ::std::cmp::max(max_peers, 1);
|
||||
light_params.config.load_share = MAX_LIGHTSERV_LOAD / max_peers as f64;
|
||||
|
||||
light_params
|
||||
}
|
||||
|
||||
impl EthSync {
|
||||
/// Creates and register protocol with the network service
|
||||
pub fn new(params: Params, connection_filter: Option<Arc<ConnectionFilter>>) -> Result<Arc<EthSync>, Error> {
|
||||
const MAX_LIGHTSERV_LOAD: f64 = 0.5;
|
||||
|
||||
let pruning_info = params.chain.pruning_info();
|
||||
let light_proto = match params.config.serve_light {
|
||||
false => None,
|
||||
@ -271,20 +300,12 @@ impl EthSync {
|
||||
.map(|mut p| { p.push("request_timings"); light_net::FileStore(p) })
|
||||
.map(|store| Box::new(store) as Box<_>);
|
||||
|
||||
let mut light_params = LightParams {
|
||||
network_id: params.config.network_id,
|
||||
config: Default::default(),
|
||||
capabilities: Capabilities {
|
||||
serve_headers: true,
|
||||
serve_chain_since: Some(pruning_info.earliest_chain),
|
||||
serve_state_since: Some(pruning_info.earliest_state),
|
||||
tx_relay: true,
|
||||
},
|
||||
sample_store: sample_store,
|
||||
};
|
||||
|
||||
let max_peers = ::std::cmp::min(params.network_config.max_peers, 1);
|
||||
light_params.config.load_share = MAX_LIGHTSERV_LOAD / max_peers as f64;
|
||||
let light_params = light_params(
|
||||
params.config.network_id,
|
||||
params.network_config.max_peers,
|
||||
pruning_info,
|
||||
sample_store,
|
||||
);
|
||||
|
||||
let mut light_proto = LightProtocol::new(params.provider, light_params);
|
||||
light_proto.add_handler(Arc::new(TxRelay(params.chain.clone())));
|
||||
@ -916,3 +937,19 @@ impl LightSyncProvider for LightSync {
|
||||
Default::default() // TODO
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn light_params_load_share_depends_on_max_peers() {
|
||||
let pruning_info = PruningInfo {
|
||||
earliest_chain: 0,
|
||||
earliest_state: 0,
|
||||
};
|
||||
let params1 = light_params(0, 10, pruning_info.clone(), None);
|
||||
let params2 = light_params(0, 20, pruning_info, None);
|
||||
assert!(params1.config.load_share > params2.config.load_share)
|
||||
}
|
||||
}
|
||||
|
@ -23,11 +23,11 @@ use std::cmp;
|
||||
use heapsize::HeapSizeOf;
|
||||
use ethereum_types::H256;
|
||||
use rlp::Rlp;
|
||||
use ethcore::block::Block;
|
||||
use ethcore::views::BlockView;
|
||||
use ethcore::header::{BlockNumber, Header as BlockHeader};
|
||||
use ethcore::client::{BlockStatus, BlockId, BlockImportError, BlockImportErrorKind};
|
||||
use ethcore::block::Block;
|
||||
use ethcore::error::{ImportErrorKind, BlockError};
|
||||
use ethcore::error::{ImportErrorKind, QueueErrorKind, BlockError};
|
||||
use sync_io::SyncIo;
|
||||
use blocks::BlockCollection;
|
||||
|
||||
@ -477,18 +477,19 @@ impl BlockDownloader {
|
||||
for block_and_receipts in blocks {
|
||||
let block = block_and_receipts.block;
|
||||
let receipts = block_and_receipts.receipts;
|
||||
|
||||
// Perform basic block verification
|
||||
if !Block::is_good(&block) {
|
||||
debug!(target: "sync", "Bad block rlp: {:?}", block);
|
||||
bad = true;
|
||||
break;
|
||||
}
|
||||
|
||||
let (h, number, parent) = {
|
||||
let header = view!(BlockView, &block).header_view();
|
||||
(header.hash(), header.number(), header.parent_hash())
|
||||
};
|
||||
|
||||
// Perform basic block verification
|
||||
if !Block::is_good(&block) {
|
||||
debug!(target: "sync", "Bad block rlp {:?} : {:?}", h, block);
|
||||
bad = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if self.target_hash.as_ref().map_or(false, |t| t == &h) {
|
||||
self.state = State::Complete;
|
||||
trace!(target: "sync", "Sync target reached");
|
||||
@ -526,6 +527,10 @@ impl BlockDownloader {
|
||||
debug!(target: "sync", "Block temporarily invalid, restarting sync");
|
||||
break;
|
||||
},
|
||||
Err(BlockImportError(BlockImportErrorKind::Queue(QueueErrorKind::Full(limit)), _)) => {
|
||||
debug!(target: "sync", "Block import queue full ({}), restarting sync", limit);
|
||||
break;
|
||||
},
|
||||
Err(e) => {
|
||||
debug!(target: "sync", "Bad block {:?} : {:?}", h, e);
|
||||
bad = true;
|
||||
|
@ -149,12 +149,6 @@ const MAX_NEW_HASHES: usize = 64;
|
||||
const MAX_NEW_BLOCK_AGE: BlockNumber = 20;
|
||||
// maximal packet size with transactions (cannot be greater than 16MB - protocol limitation).
|
||||
const MAX_TRANSACTION_PACKET_SIZE: usize = 8 * 1024 * 1024;
|
||||
// Maximal number of transactions queried from miner to propagate.
|
||||
// This set is used to diff with transactions known by the peer and
|
||||
// we will send a difference of length up to `MAX_TRANSACTIONS_TO_PROPAGATE`.
|
||||
const MAX_TRANSACTIONS_TO_QUERY: usize = 4096;
|
||||
// Maximal number of transactions in sent in single packet.
|
||||
const MAX_TRANSACTIONS_TO_PROPAGATE: usize = 64;
|
||||
// Min number of blocks to be behind for a snapshot sync
|
||||
const SNAPSHOT_RESTORE_THRESHOLD: BlockNumber = 30000;
|
||||
const SNAPSHOT_MIN_PEERS: usize = 3;
|
||||
@ -506,8 +500,9 @@ impl ChainSync {
|
||||
self.peers.clear();
|
||||
}
|
||||
|
||||
/// Reset sync. Clear all downloaded data but keep the queue
|
||||
fn reset(&mut self, io: &mut SyncIo) {
|
||||
/// Reset sync. Clear all downloaded data but keep the queue.
|
||||
/// Set sync state to the given state or to the initial state if `None` is provided.
|
||||
fn reset(&mut self, io: &mut SyncIo, state: Option<SyncState>) {
|
||||
self.new_blocks.reset();
|
||||
let chain_info = io.chain().chain_info();
|
||||
for (_, ref mut p) in &mut self.peers {
|
||||
@ -519,7 +514,7 @@ impl ChainSync {
|
||||
}
|
||||
}
|
||||
}
|
||||
self.state = ChainSync::get_init_state(self.warp_sync, io.chain());
|
||||
self.state = state.unwrap_or_else(|| ChainSync::get_init_state(self.warp_sync, io.chain()));
|
||||
// Reactivate peers only if some progress has been made
|
||||
// since the last sync round of if starting fresh.
|
||||
self.active_peers = self.peers.keys().cloned().collect();
|
||||
@ -533,7 +528,7 @@ impl ChainSync {
|
||||
io.snapshot_service().abort_restore();
|
||||
}
|
||||
self.snapshot.clear();
|
||||
self.reset(io);
|
||||
self.reset(io, None);
|
||||
self.continue_sync(io);
|
||||
}
|
||||
|
||||
@ -698,7 +693,7 @@ impl ChainSync {
|
||||
/// Called after all blocks have been downloaded
|
||||
fn complete_sync(&mut self, io: &mut SyncIo) {
|
||||
trace!(target: "sync", "Sync complete");
|
||||
self.reset(io);
|
||||
self.reset(io, Some(SyncState::Idle));
|
||||
}
|
||||
|
||||
/// Enter waiting state
|
||||
@ -761,14 +756,24 @@ impl ChainSync {
|
||||
}
|
||||
}
|
||||
|
||||
// Only ask for old blocks if the peer has a higher difficulty
|
||||
if force || higher_difficulty {
|
||||
// Only ask for old blocks if the peer has a higher difficulty than the last imported old block
|
||||
let last_imported_old_block_difficulty = self.old_blocks.as_mut().and_then(|d| {
|
||||
io.chain().block_total_difficulty(BlockId::Number(d.last_imported_block_number()))
|
||||
});
|
||||
|
||||
if force || last_imported_old_block_difficulty.map_or(true, |ld| peer_difficulty.map_or(true, |pd| pd > ld)) {
|
||||
if let Some(request) = self.old_blocks.as_mut().and_then(|d| d.request_blocks(io, num_active_peers)) {
|
||||
SyncRequester::request_blocks(self, io, peer_id, request, BlockSet::OldBlocks);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
trace!(target: "sync", "peer {} is not suitable for asking old blocks", peer_id);
|
||||
trace!(
|
||||
target: "sync",
|
||||
"peer {:?} is not suitable for requesting old blocks, last_imported_old_block_difficulty={:?}, peer_difficulty={:?}",
|
||||
peer_id,
|
||||
last_imported_old_block_difficulty,
|
||||
peer_difficulty
|
||||
);
|
||||
self.deactivate_peer(io, peer_id);
|
||||
}
|
||||
},
|
||||
|
@ -29,11 +29,9 @@ use transaction::SignedTransaction;
|
||||
use super::{
|
||||
random,
|
||||
ChainSync,
|
||||
MAX_TRANSACTION_PACKET_SIZE,
|
||||
MAX_PEER_LAG_PROPAGATION,
|
||||
MAX_PEERS_PROPAGATION,
|
||||
MAX_TRANSACTION_PACKET_SIZE,
|
||||
MAX_TRANSACTIONS_TO_PROPAGATE,
|
||||
MAX_TRANSACTIONS_TO_QUERY,
|
||||
MIN_PEERS_PROPAGATION,
|
||||
CONSENSUS_DATA_PACKET,
|
||||
NEW_BLOCK_HASHES_PACKET,
|
||||
@ -121,7 +119,7 @@ impl SyncPropagator {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let transactions = io.chain().ready_transactions(MAX_TRANSACTIONS_TO_QUERY);
|
||||
let transactions = io.chain().transactions_to_propagate();
|
||||
if transactions.is_empty() {
|
||||
return 0;
|
||||
}
|
||||
@ -184,7 +182,6 @@ impl SyncPropagator {
|
||||
|
||||
// Get hashes of all transactions to send to this peer
|
||||
let to_send = all_transactions_hashes.difference(&peer_info.last_sent_transactions)
|
||||
.take(MAX_TRANSACTIONS_TO_PROPAGATE)
|
||||
.cloned()
|
||||
.collect::<HashSet<_>>();
|
||||
if to_send.is_empty() {
|
||||
@ -205,7 +202,7 @@ impl SyncPropagator {
|
||||
let appended = packet.append_raw_checked(&transaction.drain(), 1, MAX_TRANSACTION_PACKET_SIZE);
|
||||
if !appended {
|
||||
// Maximal packet size reached just proceed with sending
|
||||
debug!("Transaction packet size limit reached. Sending incomplete set of {}/{} transactions.", pushed, to_send.len());
|
||||
debug!(target: "sync", "Transaction packet size limit reached. Sending incomplete set of {}/{} transactions.", pushed, to_send.len());
|
||||
to_send = to_send.into_iter().take(pushed).collect();
|
||||
break;
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
//! https://github.com/ethereum/wiki/wiki/Ethereum-Wire-Protocol
|
||||
//!
|
||||
|
||||
extern crate common_types as types;
|
||||
extern crate ethcore_network as network;
|
||||
extern crate ethcore_network_devp2p as devp2p;
|
||||
extern crate parity_bytes as bytes;
|
||||
|
@ -90,8 +90,8 @@ pub mod signature {
|
||||
match v {
|
||||
v if v == 27 => 0,
|
||||
v if v == 28 => 1,
|
||||
v if v > 36 => ((v - 1) % 2) as u8,
|
||||
_ => 4
|
||||
v if v >= 35 => ((v - 1) % 2) as u8,
|
||||
_ => 4
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -358,7 +358,7 @@ impl UnverifiedTransaction {
|
||||
pub fn chain_id(&self) -> Option<u64> {
|
||||
match self.v {
|
||||
v if self.is_unsigned() => Some(v),
|
||||
v if v > 36 => Some((v - 35) / 2),
|
||||
v if v >= 35 => Some((v - 35) / 2),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -387,23 +387,6 @@ impl UnverifiedTransaction {
|
||||
Ok(recover(&self.signature(), &self.unsigned.hash(self.chain_id()))?)
|
||||
}
|
||||
|
||||
/// Do basic validation, checking for valid signature and minimum gas,
|
||||
// TODO: consider use in block validation.
|
||||
#[cfg(feature = "json-tests")]
|
||||
pub fn validate(self, schedule: &Schedule, require_low: bool, allow_chain_id_of_one: bool, allow_empty_signature: bool)
|
||||
-> Result<UnverifiedTransaction, error::Error>
|
||||
{
|
||||
let chain_id = if allow_chain_id_of_one { Some(1) } else { None };
|
||||
self.verify_basic(require_low, chain_id, allow_empty_signature)?;
|
||||
if !allow_empty_signature || !self.is_unsigned() {
|
||||
self.recover_public()?;
|
||||
}
|
||||
if self.gas < U256::from(self.gas_required(&schedule)) {
|
||||
return Err(error::Error::InvalidGasLimit(::unexpected::OutOfBounds{min: Some(U256::from(self.gas_required(&schedule))), max: None, found: self.gas}).into())
|
||||
}
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Verify basic signature params. Does not attempt sender recovery.
|
||||
pub fn verify_basic(&self, check_low_s: bool, chain_id: Option<u64>, allow_empty_signature: bool) -> Result<(), error::Error> {
|
||||
if check_low_s && !(allow_empty_signature && self.is_unsigned()) {
|
||||
@ -594,6 +577,27 @@ mod tests {
|
||||
assert_eq!(t.chain_id(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn signing_eip155_zero_chainid() {
|
||||
use ethkey::{Random, Generator};
|
||||
|
||||
let key = Random.generate().unwrap();
|
||||
let t = Transaction {
|
||||
action: Action::Create,
|
||||
nonce: U256::from(42),
|
||||
gas_price: U256::from(3000),
|
||||
gas: U256::from(50_000),
|
||||
value: U256::from(1),
|
||||
data: b"Hello!".to_vec()
|
||||
};
|
||||
|
||||
let hash = t.hash(Some(0));
|
||||
let sig = ::ethkey::sign(&key.secret(), &hash).unwrap();
|
||||
let u = t.with_signature(sig, Some(0));
|
||||
|
||||
assert!(SignedTransaction::new(u).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn signing() {
|
||||
use ethkey::{Random, Generator};
|
||||
|
@ -51,18 +51,21 @@ pub enum MessageCallResult {
|
||||
}
|
||||
|
||||
/// Specifies how an address is calculated for a new contract.
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub enum CreateContractAddress {
|
||||
/// Address is calculated from nonce and sender. Pre EIP-86 (Metropolis)
|
||||
/// Address is calculated from sender and nonce. pWASM `create` scheme.
|
||||
FromSenderAndNonce,
|
||||
/// Address is calculated from code hash. Default since EIP-86
|
||||
FromCodeHash,
|
||||
/// Address is calculated from code hash and sender. Used by CREATE_P2SH instruction.
|
||||
/// Address is calculated from sender, salt and code hash. pWASM `create2` scheme and EIP-1014 CREATE2 scheme.
|
||||
FromSenderSaltAndCodeHash(H256),
|
||||
/// Address is calculated from code hash and sender. Used by pwasm create ext.
|
||||
FromSenderAndCodeHash,
|
||||
}
|
||||
|
||||
/// Externalities interface for EVMs
|
||||
pub trait Ext {
|
||||
/// Returns the storage value for a given key if reversion happens on the current transaction.
|
||||
fn initial_storage_at(&self, key: &H256) -> Result<H256>;
|
||||
|
||||
/// Returns a value for given key.
|
||||
fn storage_at(&self, key: &H256) -> Result<H256>;
|
||||
|
||||
@ -106,10 +109,13 @@ pub trait Ext {
|
||||
) -> MessageCallResult;
|
||||
|
||||
/// Returns code at given address
|
||||
fn extcode(&self, address: &Address) -> Result<Arc<Bytes>>;
|
||||
fn extcode(&self, address: &Address) -> Result<Option<Arc<Bytes>>>;
|
||||
|
||||
/// Returns code hash at given address
|
||||
fn extcodehash(&self, address: &Address) -> Result<Option<H256>>;
|
||||
|
||||
/// Returns code size at given address
|
||||
fn extcodesize(&self, address: &Address) -> Result<usize>;
|
||||
fn extcodesize(&self, address: &Address) -> Result<Option<usize>>;
|
||||
|
||||
/// Creates log entry with given topics and data
|
||||
fn log(&mut self, topics: Vec<H256>, data: &[u8]) -> Result<()>;
|
||||
@ -134,8 +140,11 @@ pub trait Ext {
|
||||
/// then A depth is 0, B is 1, C is 2 and so on.
|
||||
fn depth(&self) -> usize;
|
||||
|
||||
/// Increments sstore refunds count by 1.
|
||||
fn inc_sstore_clears(&mut self);
|
||||
/// Increments sstore refunds counter.
|
||||
fn add_sstore_refund(&mut self, value: usize);
|
||||
|
||||
/// Decrements sstore refunds counter.
|
||||
fn sub_sstore_refund(&mut self, value: usize);
|
||||
|
||||
/// Decide if any more operations should be traced. Passthrough for the VM trace.
|
||||
fn trace_next_instruction(&mut self, _pc: usize, _instruction: u8, _current_gas: U256) -> bool { false }
|
||||
|
@ -22,10 +22,12 @@ pub struct Schedule {
|
||||
pub exceptional_failed_code_deposit: bool,
|
||||
/// Does it have a delegate cal
|
||||
pub have_delegate_call: bool,
|
||||
/// Does it have a CREATE_P2SH instruction
|
||||
/// Does it have a CREATE2 instruction
|
||||
pub have_create2: bool,
|
||||
/// Does it have a REVERT instruction
|
||||
pub have_revert: bool,
|
||||
/// Does it have a EXTCODEHASH instruction
|
||||
pub have_extcodehash: bool,
|
||||
/// VM stack limit
|
||||
pub stack_limit: usize,
|
||||
/// Max number of nested calls/creates
|
||||
@ -92,6 +94,8 @@ pub struct Schedule {
|
||||
pub extcodecopy_base_gas: usize,
|
||||
/// Price of BALANCE
|
||||
pub balance_gas: usize,
|
||||
/// Price of EXTCODEHASH
|
||||
pub extcodehash_gas: usize,
|
||||
/// Price of SUICIDE
|
||||
pub suicide_gas: usize,
|
||||
/// Amount of additional gas to pay when SUICIDE credits a non-existant account
|
||||
@ -113,8 +117,10 @@ pub struct Schedule {
|
||||
pub have_bitwise_shifting: bool,
|
||||
/// Kill basic accounts below this balance if touched.
|
||||
pub kill_dust: CleanDustMode,
|
||||
/// Enable EIP-86 rules
|
||||
pub eip86: bool,
|
||||
/// Enable EIP-1283 rules
|
||||
pub eip1283: bool,
|
||||
/// VM execution does not increase null signed address nonce if this field is true.
|
||||
pub keep_unsigned_nonce: bool,
|
||||
/// Wasm extra schedule settings, if wasm activated
|
||||
pub wasm: Option<WasmCosts>,
|
||||
}
|
||||
@ -145,6 +151,10 @@ pub struct WasmCosts {
|
||||
pub opcodes_mul: u32,
|
||||
/// Cost of wasm opcode is calculated as TABLE_ENTRY_COST * `opcodes_mul` / `opcodes_div`
|
||||
pub opcodes_div: u32,
|
||||
/// Whether create2 extern function is activated.
|
||||
pub have_create2: bool,
|
||||
/// Whether gasleft extern function is activated.
|
||||
pub have_gasleft: bool,
|
||||
}
|
||||
|
||||
impl Default for WasmCosts {
|
||||
@ -162,6 +172,8 @@ impl Default for WasmCosts {
|
||||
max_stack_height: 64*1024,
|
||||
opcodes_mul: 3,
|
||||
opcodes_div: 8,
|
||||
have_create2: false,
|
||||
have_gasleft: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -197,6 +209,7 @@ impl Schedule {
|
||||
have_revert: false,
|
||||
have_return_data: false,
|
||||
have_bitwise_shifting: false,
|
||||
have_extcodehash: false,
|
||||
stack_limit: 1024,
|
||||
max_depth: 1024,
|
||||
tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0],
|
||||
@ -229,6 +242,7 @@ impl Schedule {
|
||||
copy_gas: 3,
|
||||
extcodesize_gas: 700,
|
||||
extcodecopy_base_gas: 700,
|
||||
extcodehash_gas: 400,
|
||||
balance_gas: 400,
|
||||
suicide_gas: 5000,
|
||||
suicide_to_new_account_cost: 25000,
|
||||
@ -238,7 +252,8 @@ impl Schedule {
|
||||
blockhash_gas: 20,
|
||||
have_static_call: false,
|
||||
kill_dust: CleanDustMode::Off,
|
||||
eip86: false,
|
||||
eip1283: false,
|
||||
keep_unsigned_nonce: false,
|
||||
wasm: None,
|
||||
}
|
||||
}
|
||||
@ -268,6 +283,7 @@ impl Schedule {
|
||||
have_revert: false,
|
||||
have_return_data: false,
|
||||
have_bitwise_shifting: false,
|
||||
have_extcodehash: false,
|
||||
stack_limit: 1024,
|
||||
max_depth: 1024,
|
||||
tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0],
|
||||
@ -300,6 +316,7 @@ impl Schedule {
|
||||
copy_gas: 3,
|
||||
extcodesize_gas: 20,
|
||||
extcodecopy_base_gas: 20,
|
||||
extcodehash_gas: 400,
|
||||
balance_gas: 20,
|
||||
suicide_gas: 0,
|
||||
suicide_to_new_account_cost: 0,
|
||||
@ -309,7 +326,8 @@ impl Schedule {
|
||||
blockhash_gas: 20,
|
||||
have_static_call: false,
|
||||
kill_dust: CleanDustMode::Off,
|
||||
eip86: false,
|
||||
eip1283: false,
|
||||
keep_unsigned_nonce: false,
|
||||
wasm: None,
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user