Compare commits

..

72 Commits

Author SHA1 Message Date
Talha Cross
ecbafb2390 backports for beta 2.5.2 (#10737)
* version: bump beta to 2.5.2

* [CI] allow cargo audit to fail (#10676)

* [CI] allow cargo audit to fail

* [.gitlab-ci.yml] add a comment about cargo audit

* [Cargo.lock] cargo update -p protobuf

* Reset blockchain properly (#10669)

* delete BlockDetails from COL_EXTRA

* better proofs

* added tests

* PR suggestions

* new image (#10673)

* Update publishing (#10644)

* docker images are now built on k8s: test run

* copy check_sync.sh in build-linux job

* copy scripts/docker/hub/* in build-linux job

* removed cache var

* cleanup, no more nightly dockers

* cleanup in dockerfile

* some new tags

* removed sccsche debug log, cleanup

* no_gits, new artifacts dir, changed scripts. Test run.

* define version once

* one source for TRACK

* stop kovan onchain updates

* moved changes for two images to a new branch

* rename Dockerfile

* no need in libudev-dev

* enable lto for release builds (#10717)

* Use RUSTFLAGS to set the optimization level (#10719)

* Use RUSTFLAGS to set the optimization level

Cargo has a [quirk]() in how configuration settings are propagated when `cargo test` runs: local code respect the settings in `[profile.test]` but all dependencies use the `[profile.dev]` settings. Here we force `opt-level=3` for all dependencies.

* Remove unused profile settings

* Maybe like this?

* Turn off incremental compilation

* Remove colors; try again with overflow-checks on

* Use quiet CI machine

* Turn overflow checking back on

* Be explicit about what options we use

* Remove "quiet machine" override

* ethcore: enable ECIP-1054 for classic (#10731)

* config: enable atlantis on ethereum classic

* config: enable atlantis on morden classic

* config: enable atlantis on morden classic

* config: enable atlantis on kotti classic

* ethcore: move kotti fork block to 0xAEF49

* ethcore: move morden fork block to 0x4829BA

* ethcore: move classic fork block to 0x81B320

* remove trailing comma

* remove trailing comma

* fix chainspec

* ethcore: move classic fork block to 0x7fffffffffffffff
2019-06-11 20:56:03 +02:00
Talha Cross
adabd8198c beta ci: backport missing diff from master (#10661)
* ci: publish docs debug (#10638)

* ci: backport missing diff from master
2019-05-14 15:03:29 +02:00
Talha Cross
c2487cfe07 ci: publish docs debug (#10638) (#10660) 2019-05-14 14:04:54 +02:00
Talha Cross
e0141f8324 beta 2.5.1 (#10643)
* version: bump beta to 2.5.1

* fix(whisper expiry): current time + work + ttl (#10587)

* update bootnodes (#10595)

* config: update goerli bootnodes

* config: update kotti bootnodes

* adds rpc error message for --no-ancient-blocks (#10608)

* adds error message for --no-ancient-blocks, closes #10261

* Apply suggestions from code review

Co-Authored-By: seunlanlege <seunlanlege@gmail.com>

* Constantinople HF on POA Core (#10606)

* Constantinople HF on POA Core

Plan Constantinople/St.Petersfork HF on POA Core network at block 8582254.
Original PR in POA repository: https://github.com/poanetwork/poa-chain-spec/pull/110

* Remove extra empty line

* evm: add some mulmod benches (#10600)

* evm: add blockhash_mulmod bench

* evm: use num-bigint for mod ops

* Clique: zero-fill extradata when the supplied value is less than 32 bytes in length (#10605)

* Update kovan.json to switch validator set to POA Consensus Contracts (#10628)

* Fix publish docs (#10635)

* Fix publish docs

* this never should be forced, either way compiling previous versions will produce outdated docs

* fix array, var was moved to the group project global variables list

* Fix rinkeby petersburg fork (#10632)
2019-05-10 13:48:52 +02:00
Talha Cross
b52ac20660 beta backports (#10576)
* Reject crazy timestamps instead of truncating.

* fix(light cull): poll light cull instead of timer (#10559)

* fix(light cull): poll light cull instead of timer

* fix(grumbles): remove error + updated docs

* fix(on-demand request): `expect()` reason

* docs(remove misleading info)
2019-04-08 11:44:10 +02:00
soc1c
3c85f29f11 version: betalize 2.5 2019-04-02 09:37:43 +02:00
Andrew Jones
d9673b0d6b tx-pool: check transaction readiness before replacing (#10526)
* Update to vanilla tx pool error

* Prevent a non ready tx replacing a ready tx

* Make tests compile

* Test ready tx not replaced by future tx

* Transaction indirection

* Use StateReadiness to calculate Ready in `should_replace`

* Test existing txs from same sender are used to compute Readiness

* private-tx: Wire up ShouldReplace

* Revert "Use StateReadiness to calculate Ready in `should_replace`"

This reverts commit af9e69c8

* Make replace generic so it works with private-tx

* Rename Replace and add missing docs

* ShouldReplace no longer mutable

* tx-pool: update to transaction-pool 2.0 from crates.io

* tx-pool: generic error type alias

* Exit early for first unmatching nonce

* Fix private-tx test, use existing write lock

* Use read lock for pool scoring
2019-04-01 10:48:51 +02:00
Niklas Adolfsson
89f828be1c fix(light account response): update tx_queue (#10545) 2019-03-31 11:54:19 +02:00
Thibaut Sardan
ec56b1f09d Update light client harcoded headers (#10547)
* kovan #10643457

* ropsten #5296129

* foundation #7460865

* classic #7747585

* indentation

* morden #3973121
2019-03-31 11:46:36 +02:00
Niklas Adolfsson
95236d25b2 fix(light eth_gasPrice): ask network if not in cache (#10535)
* fix(light eth_gasPrice): ask N/W if not in cache

* fix(bad rebase)
2019-03-31 10:40:33 +02:00
Vladyslav Lupashevskyi
7b2afdfc8c Implement caching for service transactions checker (#10088)
* Tx permission contract improvement

* Take in account zero gas price certification when doing transact_contract

* DRY in ServiceTransactionChecker

* Fix typos and regroup mod

* Introduce CertifiedAddressesCache

* Introduce refresh_cache for CertifiedAddressesCache

* Add CertifiedAddressesCache read and write on checking

* Refresh CertifiedAddressesCache on new imported block

* Separate ChainInfo trait and fix errors after merge

* Do not fire an error when service txes contract does not exist

* WIP: Shared certified addresses cache between miner and client + use HashMap instead of BTreeMap

* Refactor refresh_cache for ServiceTransactionChecker

* Refresh cache fixes

* Add cache read in check_address + log when cache is used + improve code

* Remove ChainInfo from ServiceTransaction dependencies

* DRY ServiceTransactionChecker

* Fix Client and Miner in tests

* Fix node_filter test

* Fix Client::new in add_peer_with_private_config

* WIP: Separated ChainNotify from ethcore trait and implemented ChainNotify for ServiceTransactionChecker

* Fix watcher test

* Revert "Merge branch 'master' into master"

This reverts commit 4e7371dc109d022efe3087defc33d827998ce648, reversing
changes made to bffd73e5fd58a516bbf404281b51cf26422e181e.

* Revert "Fix watcher test"

This reverts commit bffd73e5fd58a516bbf404281b51cf26422e181e.

* Revert "WIP: Separated ChainNotify from ethcore trait and implemented ChainNotify for ServiceTransactionChecker"

This reverts commit 6e73d1e61fa15dc10ffd4fab63df29eabe9c3b3a.

* Revert "Fix Client::new in add_peer_with_private_config"

This reverts commit ec610a30bee95588d58b79edcc9e43c2ff90f1ad.

* Revert "Fix node_filter test"

This reverts commit 06a4b2de86317c902f579e912b40de0b0fbf6d78.

* Revert "Fix Client and Miner in tests"

This reverts commit 51bbad330ea6e7bdfc1516208cc8705d5d11516d.

* Implement ServiceTransactionChecker in miner and delegate it to client + revert unnecessary changes

* Merge master

* Code improvements

* Merge branch 'master' of https://github.com/paritytech/parity-ethereum

# Conflicts:
#	Cargo.lock
#	ethcore/private-tx/src/lib.rs
#	ethcore/src/miner/miner.rs
#	ethcore/src/miner/pool_client.rs
2019-03-31 10:39:38 +02:00
TriplEight
440e52f410 build android with cache, win fixes (#10546)
* build android with cache!

* windows fixes

* windows fixes 2

* windows fixes 3

* windows fixes 4

* windows should have sccache variables in env variables
2019-03-30 20:29:08 +01:00
jwasinger
8840a293dd clique: make state backfill time measurement more accurate (#10551) 2019-03-30 20:28:32 +01:00
Marek Kotewicz
89d627769e updated lru-cache to 0.1.2 (#10542) 2019-03-29 12:25:15 +00:00
TriplEight
4e2e88a620 separate docker image to build docs (#10543) 2019-03-28 17:19:00 +01:00
Niklas Adolfsson
ebf51c0be0 fix(bump dependencies) (#10540)
* cargo update -p log:0.4.5

* cargo update -p regex:1.0.5

* cargo update -p parking_lot

* cargo update -p serde_derive

* cargo update -p serde_json

* cargo update -p serde

* cargo update -p lazy_static

* cargo update -p num_cpus

* cargo update -p toml
2019-03-28 15:31:06 +00:00
Wei Tang
04c6867660 Fix max_gas (#10537)
Fix max_gas
2019-03-27 15:53:06 -04:00
soc1c
0199acbece ethcore: remove eth social and easthub chain configs (#10531) 2019-03-27 15:07:38 +01:00
Denis S. Soldatov aka General-Beck
e4c2fe9e72 Initial support sccache for windows build (#10520)
* Initial support sccache for win build

* show sccache stats

* cache paths for shared runners

* sccache status is in the script.

* removed windows test for now
2019-03-27 14:47:08 +01:00
Niklas Adolfsson
407de5e8c4 fix(light): make OnDemand generic instead of using the concrete type (#10514)
* ethcore: add clique engine (#9981)

* fix broken sync

* correct seal fields

* ethcore: fix comment

* parity: remove duplicate params

* clique: fix whitespaces

* ethcore: fix goerli chain spec

* refactor signer_snapshot into pending/finalized state

* move close_block_extra_data after seal is applied

* refactor most of the logic into the signer_snapshot

* clique: refactor locking logic out of the consensus engine interface

* Fix jsonspec and add an unittest

* Replace space with tabs

* Unbroke sync

* Fix broken sync

* 1/2 state tracking without votes

* 2/2 implement vote tracking

* ci: use travis for goerli

* ci: setup a clique network

* ci: sync a görli node

* add clique deploy script

* ci: fix paths in clique deploy script

* ci: use docker compose

* ci: fix travis job names

* ci: fix build deps

* ci: massively reduce tests

* Revert "ci: massively reduce tests"

This reverts commit 6369f0b069ed2607a7e9f2e1d85489bacdc43384.

* ci: run cargo test directly

* ci: separate build and test stages

* ci: cache rust installation

* ci: simplify ci stages

* ci: make clique deploy script executable

* ci: shutdown goerli sync after 20min

* ci: remove slow sync stage

* ci: use timeout to finish jobs

* ci: fix build path

* ci: use absolute paths to end this confusion

* ci: add geth and parity to path

* ci: be more verbose

* ci: allow for more relaxed caching timeout

* ci: update repositories for custom ppa

* ci: fix typo in file name

* ci: fix docker compose file

* ci: add ethkey to docker

* ci: make sure deploy script is up to date with upstream

* ci: stop docker container after certain time

* ci: force superuser to update permissions on docker files

* ci: reduce run time of script to ~30 min

* ci: remove duplicate caching in travis

* remove trace statements

* clique: add more validation involving the recent signer list

* ethcore: enable constantinople for rinkeby

* ethcore: fix whitespaces in rinkeby spec

* ethcore: reformat goerli.json

* Revert "ci: remove duplicate caching in travis"

This reverts commit a562838d3d194d37f9871dcbe00b783637978f89.

* tmp commit

* another tmp commit

* it builds!

* add sealing capabilities

* add seal_header hook to allow separation of block seal/importing code paths

* clique: remove populate_from_parent.

* add panic

* make turn delay random

* initialize OpenBlock properly in 'enact'

* misc: remove duplicate lines

* misc: fix license headers

* misc: convert spaces to tabs

* misc: fix tabs

* Update Cargo.toml

* Update Cargo.toml

* Update Cargo.toml

* clique: ensure validator restores state before trying to seal

* clique: make 'state' return an Error.  Make some error messages more clear

* Fix compile error after rebase & toolchain upgrade

* fix a bunch of import warnings

* Refactor code

* Fix permissions

* Refactoring syncing

* Implement full validator checks

* Refactor util functions to seperate file

* mining 1

* ethcore: add chainspec for kotti

* ethcore: rename pre-goerli configs

* ethcore: load kotti chain spec

* cli: add kotti to params

* Implement working local sealing

* making sealing & syncing work together

* Relax timestamp checking

* ethcore: prepare for the real goerli to launch

* Implement NOTURN wiggle properly & cleanupnup warnings

* Implement vote casting

* Update docs & skip signing if no signer

* Optimize step-service interval

* Record state on local sealed block

* Fix script filemode

* Cleaning up codebase

* restore enact trace logging

* Delete clique.sh and move sync.sh

* remove travis.yml

* Remove dead code

* Cleanup compile warning

* address review comments

* adding more comments and removing unwrap()

* ci: remove sync script

* Address review comments

* fix compile error

* adding better debugging for timing

* Implement an dedicated thread for sealing timing

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

* fix(add helper timestamp overflows)

* fix(simplify code)

* fix(make helper private)

* snap: official image / test (#10168)

* official image / test

* fix / test

* bit more necromancy

* fix paths

* add source bin/df /test

* add source bin/df /test2

* something w paths /test

* something w paths /test

* add source-type /test

* show paths /test

* copy plugin /test

* plugin -> nil

* install rhash

* no questions while installing rhash

* publish snap only for release

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

* fix(docker): fix not receives SIGINT

* fix: update with reviews

* update with review

* update

* update

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

* Don't add discovery initiators to the node table

* Use enums for tracking state of the nodes in discovery

* Dont try to ping ourselves

* Fix minor nits

* Update timeouts when observing an outdated node

* Extracted update_bucket_record from update_node

* Fixed typo

* Fix two final nits from @todr

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

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

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

* Bundle protocol and packet_id together in chain sync (#10315)

Define a new `enum` where devp2p subprotocol packet ids (currently eth and par) are defined. Additionally provide functionality to query id value and protocol of a given id object.

* snap: prefix version and populate candidate channel (#10343)

* snap: populate candidate releases with beta snaps to avoid stale channel

* snap: prefix version with v*

* addressing review comments

* engine: fix copyright header

* scripts: restore permissions on sign command

* ethcore: enforce tabs

* ethcore: enforce tabs

* ethcore: enforce tabs

* addressing comments

* addressing comments

* addressing more comments

* addressing more comments

* addressing more comments

* addressing more comments

* addressing more comments

* json-spec: fix clique epoch to non-zero u64

* ci: enable travis for parity goerli

* ci: don't separate build and test step

* ci: don't run c++ tests on travis

* ci: simplify cargo test to squeeze into travis timeout

* ci: don't run tests on travis at all

* style(fixes)

* fix(add tests)

* fix(recent_signer bug)

* fix(complete all tests)

* fix(nits)

* fix(simplify asserts)

* fix(cliqueState): simplify code

* fix(nits)

* docs(comments what's need to fixed)

* fix(revert unintended changes)

* fix(tests)

* fix(logs): voting logs

* fix(readability + more logs)

* fix(sync)

* docs(add missing licens header)

* fix(log): info! -> trace!

* docs(fix nits) + fix(remove assert)

* perf(use counter instead of vec)

* fix(remove needless block in match)

* fix(faulty comment)

* grumbles(docs for tests)

* fix(nits)

* fix(revert_vote): only remove vote when votes == 0

* fix(vote counter): checked arithmetics

* fix(simplify tests)

* fix(nits)

* fix(clique): err types

* fix(clique utils): make use of errors

* fix(cleanup nits)

* fix(clique sealing): don't read state no signer

* fix(replace Vec<Signers> with BTreeSet<Signers>)

* fix(tests): BTreeSet and more generic helpers

* fix(nits)

* fix(ethcore_block_seal): remove needless `Box`

* fix(faulty log): info -> trace

* fix(checked SystemTime): prevent SystemTime panics

* style(chain cfg): space after `:`

* style(fn enact): fix whitespace

* docs(clique): StepService

* docs(nit): fix faulty comment

* docs(fix typo)

* style(fix bad indentation)

* fix(bad regex match)

* grumble(on_seal_block): make `&mut` to avoid clone

* docs(on_seal_block): fix faulty documentation

* Delete .travis.yml

* docs: remove eth hf references in spec

* Update client.rs

* fix(nits)

* fix(clique step): `RwLock` -> `AtomicBool`

* fix(clique): use `Duration::as_millis`

* Clean up some Clique documentation

* Add trace information to eth_estimateGas (#10519)

* Add trace information to eth_estimateGas

* replace unwrap better version

* change vm::Error formatter to more user-friendly

* remove extra error format

* use map_or instead sequence of map/unwrap_or

* fix(light/on_demand): extract as a trait

* fix(grumble): OnDemand remove needless trait bound
2019-03-27 14:46:20 +01:00
Andrew Jones
7d26a82232 private-tx: replace error_chain (#10510)
* Update to vanilla tx pool error

* private-tx: remove error-chain, implement Error, derive Display

* private-tx: replace ErrorKind and bail!

* private-tx: add missing From impls and other compiler errors

* private-tx: use original tx-pool error

* Don't be silly cargo
2019-03-27 14:46:05 +01:00
Kirill Fomichev
3b23817936 Add trace information to eth_estimateGas (#10519)
* Add trace information to eth_estimateGas

* replace unwrap better version

* change vm::Error formatter to more user-friendly

* remove extra error format

* use map_or instead sequence of map/unwrap_or
2019-03-27 14:21:08 +01:00
5chdn
aa8487c1d0 ethcore: add clique engine (#9981)
* fix broken sync

* correct seal fields

* ethcore: fix comment

* parity: remove duplicate params

* clique: fix whitespaces

* ethcore: fix goerli chain spec

* refactor signer_snapshot into pending/finalized state

* move close_block_extra_data after seal is applied

* refactor most of the logic into the signer_snapshot

* clique: refactor locking logic out of the consensus engine interface

* Fix jsonspec and add an unittest

* Replace space with tabs

* Unbroke sync

* Fix broken sync

* 1/2 state tracking without votes

* 2/2 implement vote tracking

* ci: use travis for goerli

* ci: setup a clique network

* ci: sync a görli node

* add clique deploy script

* ci: fix paths in clique deploy script

* ci: use docker compose

* ci: fix travis job names

* ci: fix build deps

* ci: massively reduce tests

* Revert "ci: massively reduce tests"

This reverts commit 6369f0b069ed2607a7e9f2e1d85489bacdc43384.

* ci: run cargo test directly

* ci: separate build and test stages

* ci: cache rust installation

* ci: simplify ci stages

* ci: make clique deploy script executable

* ci: shutdown goerli sync after 20min

* ci: remove slow sync stage

* ci: use timeout to finish jobs

* ci: fix build path

* ci: use absolute paths to end this confusion

* ci: add geth and parity to path

* ci: be more verbose

* ci: allow for more relaxed caching timeout

* ci: update repositories for custom ppa

* ci: fix typo in file name

* ci: fix docker compose file

* ci: add ethkey to docker

* ci: make sure deploy script is up to date with upstream

* ci: stop docker container after certain time

* ci: force superuser to update permissions on docker files

* ci: reduce run time of script to ~30 min

* ci: remove duplicate caching in travis

* remove trace statements

* clique: add more validation involving the recent signer list

* ethcore: enable constantinople for rinkeby

* ethcore: fix whitespaces in rinkeby spec

* ethcore: reformat goerli.json

* Revert "ci: remove duplicate caching in travis"

This reverts commit a562838d3d194d37f9871dcbe00b783637978f89.

* tmp commit

* another tmp commit

* it builds!

* add sealing capabilities

* add seal_header hook to allow separation of block seal/importing code paths

* clique: remove populate_from_parent.

* add panic

* make turn delay random

* initialize OpenBlock properly in 'enact'

* misc: remove duplicate lines

* misc: fix license headers

* misc: convert spaces to tabs

* misc: fix tabs

* Update Cargo.toml

* Update Cargo.toml

* Update Cargo.toml

* clique: ensure validator restores state before trying to seal

* clique: make 'state' return an Error.  Make some error messages more clear

* Fix compile error after rebase & toolchain upgrade

* fix a bunch of import warnings

* Refactor code

* Fix permissions

* Refactoring syncing

* Implement full validator checks

* Refactor util functions to seperate file

* mining 1

* ethcore: add chainspec for kotti

* ethcore: rename pre-goerli configs

* ethcore: load kotti chain spec

* cli: add kotti to params

* Implement working local sealing

* making sealing & syncing work together

* Relax timestamp checking

* ethcore: prepare for the real goerli to launch

* Implement NOTURN wiggle properly & cleanupnup warnings

* Implement vote casting

* Update docs & skip signing if no signer

* Optimize step-service interval

* Record state on local sealed block

* Fix script filemode

* Cleaning up codebase

* restore enact trace logging

* Delete clique.sh and move sync.sh

* remove travis.yml

* Remove dead code

* Cleanup compile warning

* address review comments

* adding more comments and removing unwrap()

* ci: remove sync script

* Address review comments

* fix compile error

* adding better debugging for timing

* Implement an dedicated thread for sealing timing

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

* fix(add helper timestamp overflows)

* fix(simplify code)

* fix(make helper private)

* snap: official image / test (#10168)

* official image / test

* fix / test

* bit more necromancy

* fix paths

* add source bin/df /test

* add source bin/df /test2

* something w paths /test

* something w paths /test

* add source-type /test

* show paths /test

* copy plugin /test

* plugin -> nil

* install rhash

* no questions while installing rhash

* publish snap only for release

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

* fix(docker): fix not receives SIGINT

* fix: update with reviews

* update with review

* update

* update

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

* Don't add discovery initiators to the node table

* Use enums for tracking state of the nodes in discovery

* Dont try to ping ourselves

* Fix minor nits

* Update timeouts when observing an outdated node

* Extracted update_bucket_record from update_node

* Fixed typo

* Fix two final nits from @todr

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

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

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

* Bundle protocol and packet_id together in chain sync (#10315)

Define a new `enum` where devp2p subprotocol packet ids (currently eth and par) are defined. Additionally provide functionality to query id value and protocol of a given id object.

* snap: prefix version and populate candidate channel (#10343)

* snap: populate candidate releases with beta snaps to avoid stale channel

* snap: prefix version with v*

* addressing review comments

* engine: fix copyright header

* scripts: restore permissions on sign command

* ethcore: enforce tabs

* ethcore: enforce tabs

* ethcore: enforce tabs

* addressing comments

* addressing comments

* addressing more comments

* addressing more comments

* addressing more comments

* addressing more comments

* addressing more comments

* json-spec: fix clique epoch to non-zero u64

* ci: enable travis for parity goerli

* ci: don't separate build and test step

* ci: don't run c++ tests on travis

* ci: simplify cargo test to squeeze into travis timeout

* ci: don't run tests on travis at all

* style(fixes)

* fix(add tests)

* fix(recent_signer bug)

* fix(complete all tests)

* fix(nits)

* fix(simplify asserts)

* fix(cliqueState): simplify code

* fix(nits)

* docs(comments what's need to fixed)

* fix(revert unintended changes)

* fix(tests)

* fix(logs): voting logs

* fix(readability + more logs)

* fix(sync)

* docs(add missing licens header)

* fix(log): info! -> trace!

* docs(fix nits) + fix(remove assert)

* perf(use counter instead of vec)

* fix(remove needless block in match)

* fix(faulty comment)

* grumbles(docs for tests)

* fix(nits)

* fix(revert_vote): only remove vote when votes == 0

* fix(vote counter): checked arithmetics

* fix(simplify tests)

* fix(nits)

* fix(clique): err types

* fix(clique utils): make use of errors

* fix(cleanup nits)

* fix(clique sealing): don't read state no signer

* fix(replace Vec<Signers> with BTreeSet<Signers>)

* fix(tests): BTreeSet and more generic helpers

* fix(nits)

* fix(ethcore_block_seal): remove needless `Box`

* fix(faulty log): info -> trace

* fix(checked SystemTime): prevent SystemTime panics

* style(chain cfg): space after `:`

* style(fn enact): fix whitespace

* docs(clique): StepService

* docs(nit): fix faulty comment

* docs(fix typo)

* style(fix bad indentation)

* fix(bad regex match)

* grumble(on_seal_block): make `&mut` to avoid clone

* docs(on_seal_block): fix faulty documentation

* Delete .travis.yml

* docs: remove eth hf references in spec

* Update client.rs

* fix(nits)

* fix(clique step): `RwLock` -> `AtomicBool`

* fix(clique): use `Duration::as_millis`

* Clean up some Clique documentation

Co-authored-by: soc1c <soc1c@users.noreply.github.com>
Co-authored-by: HCastano <HCastano@users.noreply.github.com>
Co-authored-by: niklasad1 <niklasad1@users.noreply.github.com>
Co-authored-by: jwasinger <jwasinger@users.noreply.github.com>
Co-authored-by: ChainSafe <ChainSafe@users.noreply.github.com>
Co-authored-by: thefallentree <thefallentree@users.noreply.github.com>
Co-authored-by: 5chdn <5chdn@users.noreply.github.com>
2019-03-27 14:13:24 +01:00
TriplEight
9cb8606103 verbose flag for cpp tests (#10524) 2019-03-26 12:37:45 +01:00
Hernando Castano
6cf3ba7efd Add a more realistic Batch test (#10511)
* Remove unrealistic tests

* Add test that more closely resembles real usage
2019-03-25 10:42:33 +01:00
Sočik
023e511f83 docs: add changelogs for 2.3.{6,7,8} and 2.4.{1,2,3} (#10494)
* docs: add changelogs for 2.3.{6,7} and 2.4.{1,2}

* docs: add changelogs for 2.4.3 beta and 2.3.8 stable

* Update docs/CHANGELOG-2.3.md

Co-Authored-By: soc1c <47772477+soc1c@users.noreply.github.com>

* Update docs/CHANGELOG-2.3.md

Co-Authored-By: soc1c <47772477+soc1c@users.noreply.github.com>

* docs: remove empty lines
2019-03-22 15:59:20 +01:00
Niklas Adolfsson
17042e9c32 fix(rpc): fix a bunch of clippy lints (#10493)
* fix(rpc): fix a bunch of clippy lints

* fix(rpc clippy): remove unused ignored lints

* fix(clippy): fix all redundant_field_names

This commit fixes all uses of `redundant_field_names` and removes the ignored lint `redundant_field_names`

* fix(brain unwrap): replace with expect
2019-03-22 12:01:11 +01:00
Denis S. Soldatov aka General-Beck
f2c34f7ca2 fix Sha3/keccak256 hash calculation for binaries (#10509)
https://github.com/paritytech/parity-ethereum/issues/10495
2019-03-22 11:46:57 +01:00
Hernando Castano
375a8daeb4 Add additional request tests (#10503) 2019-03-21 17:37:13 +01:00
Guillaume Ballet
b700ff3501 whisper/cli: add p2p port and ip parameters (#10057)
* whisper/cli: add p2p port and ip parameters

This is so that those params don't change randomly and are in sync with the URL that
is displayed.

* feedback: Result instead of panic

Co-Authored-By: gballet <gballet@gmail.com>

* feedback: Map error in port conversion

Co-Authored-By: gballet <gballet@gmail.com>

* whisper/cli: User can specify enode private key

So that the enode doesn't change at every run.

* whipser/cli: finish integrating review feedback.

* Accomodate error API change

* Update rustc-hex version in whisper/cli/Cargo.toml

Co-Authored-By: gballet <gballet@gmail.com>

* Update README with new whisper cli options

* Fix typo in error message

Co-Authored-By: gballet <gballet@gmail.com>

* Fix Cargo.lock and build issue after lib version upgrade

* Fix another typo

Co-Authored-By: gballet <gballet@gmail.com>
2019-03-21 17:45:02 +03:00
Niklas Adolfsson
9519493e32 fix(time-utils): add missing license (#10497) 2019-03-20 16:01:38 +01:00
Niklas Adolfsson
037fd1b309 fix(extract timestamp_checked_add as lib) (#10383)
* fix(extract `timestamp_checked_add` as lib)

* fix(whisper types): remove unused `EmptyTopics`

* fix(time-lib): feature-flag to use time-lib or std

This commit adds conditional compilation checks that falls back to `our time-lib` when
`time_checked_add` is not available in the standard library

Note, `time_checked_add` covers both `checked_add` and `checked_sub`

* fix(grumble): use cfg_attr to define rustc feature
2019-03-19 23:17:05 +01:00
Niklas Adolfsson
78a534633d fix(rpc): lint unused_extern_crates + fix warns (#10489) 2019-03-19 16:37:24 +01:00
Denis S. Soldatov aka General-Beck
effead9ba5 fix win&mac build (#10486)
add CARGO_HOME:                      "${CI_PROJECT_DIR}/.cargo"
2019-03-19 11:39:44 +01:00
TriplEight
a8ee3c97e6 Сaching through docker volume (#10477)
* _old codebase_ before docker update

* before docker update, testing runnr

* docker update, testing the caching

* distributed job cargo homes

* distributed job cargo homes 2

* distributed job cargo homes 3

* dockerfile with gitlab checkout, audit uses template

* dockerfile gets repo in volume

* change builds_dir

* trying docker cache for repo

* repo cached automatically

* after script is not concatenated

* check sccache non-cacheable reasons nature

* watch cache

* log sccache

* log sccache 2

* debug log sccache

* fix debug log sccache

* fix debug log sccache 2

* debug log cache 3

* debug log cache 3

* trace log all sccache

* test wo cargo cache

* test w removed cargo cache

* report non-cacheable reasons, cargo cache is back and empty

* report non-cacheable reasons, cargo cache is back and empty 2

* report non-cacheable reasons, cargo cache is back and empty 3

* wrap into after_script

* restore CI tags

`qa` -> `linux-docker`

* return to main runners, this will fail until config on runners And Dockerfile won't be updated

* typo fix CI lint

* return to docker tag
2019-03-19 03:14:59 +03:00
Marek Kotewicz
fb461659c7 OpenBlock::new take IntoIterator instead of mutable ref to Iterator (#10480) 2019-03-15 15:43:54 +01:00
Marek Kotewicz
a574df3132 simplify block module and usage (#10479)
* removed trait IsBlock and simplify block usage

* removed redundant ClosedBlock::hash function
2019-03-15 12:22:47 +00:00
Marek Kotewicz
d83143d0ba remove unused Engine::maximum_uncle_age (#10476) 2019-03-14 21:34:26 +01:00
Marek Kotewicz
f875175325 remove unused Engine::is_proposal (#10475) 2019-03-14 12:40:59 +00:00
Marek Kotewicz
c9db8ea21d further simplify machine (#10472)
* removed AuxiliaryRequest from Machin trait

* removed AncestryAction from Machine trait

* removed AuxiliaryData from Machine trait

* removed LocalizedMachine trait
2019-03-14 11:28:15 +01:00
Marek Kotewicz
a16bad4175 simplify parity machine (#10469)
* simplify ethcore machine by removing redundant traits

* further ethereum machine simplifications

* removed obsolete todo
2019-03-13 11:36:13 +01:00
Hernando Castano
595dac6c3f Ensure static validator set changes are recognized (#10467) 2019-03-12 19:16:29 +01:00
TriplEight
82a148a99b Tests parallelized (#10452)
* tests splitted, phase 1

* typo

* fix wrong launch commands

* typos

* rearrangements

* use `nproc` function for threads

* use nproc for threads

* let theads be auto, build-andriod no more in regular run

* split val chain and cargo check

* renamed some files

* wrong phase

* check rust files before test jobs

* lint error

* rust files modivied var

* test except changes

* add rust_changes except

* lint error

* fixes

* .gitlab-ci.yml can't be excluded

* pipeline shouldn't start

* pipeline must go

* pipeline must go 2

* pipeline must go 3

* pipeline must go 4

* pipeline must go 5

* pipeline must go 6

* pipeline must go 7

* pipeline must not go 1

* pipeline must go 8

* avoid skippng tests yet, reintroducing them after the caching

* test theory

* parallelized cargo check with combusting helicopters

* less uploads

* alias for cargo checks

* nice template
2019-03-11 15:26:35 +01:00
Niklas Adolfsson
4320c9bc4f docs(spec): remove link to obsolete issue (#10464) 2019-03-11 11:48:01 +01:00
Marek Kotewicz
23d977ecce simplify ethcore machine by removing redundant traits (#10454) 2019-03-11 10:37:48 +00:00
5chdn
ab27848dc4 docs: update changelogs for 2.2.{8,9,10,11}, 2.3.{1,2,3,4,5}, and 2.4.0 (#10389)
* docs: move changelog 2-3 to docs/

* docs: fix changelog 2-3 path

* docs: add changelogs for 2.2.{8,9,10,11}

* docs: add changelogs for 2.3.{1,2,3,4}

* Update CHANGELOG.md

* Update CHANGELOG-2.3.md

* Update CHANGELOG.md

* Update CHANGELOG.md
2019-03-07 21:11:58 +01:00
Denis S. Soldatov aka General-Beck
742a6007fe Revert "CI aws git checkout (#10451)" (#10456)
* Revert "CI aws git checkout (#10451)"

This reverts commit 3e1d73126c.

* Update .gitlab-ci.yml

revert aws script with small fixes

* Delete publish-aws.sh
2019-03-07 14:45:35 +03:00
Niklas Adolfsson
91933d857d perf(ethcore): micro-opt (#10405)
Mostly fixes that changes `eagerly eval` to `lazy eval`
2019-03-06 15:30:35 +01:00
Denis S. Soldatov aka General-Beck
3e1d73126c CI aws git checkout (#10451)
* Updating the CI system with the publication of releases and binary files on github

Signed-off-by: Denis S. Soldatov aka General-Beck <general.beck@gmail.com>

* move publish aws from gitlab.yml to gitlab scripts

Signed-off-by: Denis S. Soldatov aka General-Beck <general.beck@gmail.com>

* gitlab.yml cleaning
move publish AWS to gitlab scripts
remove dependencies from android build

Signed-off-by: Denis S. Soldatov aka General-Beck <general.beck@gmail.com>

* Revert "Updating the CI system with the publication of releases and binary files on github"

This reverts commit da87e06f2e4751dbca08a898b52926aef5ad0aba.

* remove no-git for aws

* microfix

* no need in no_git then
2019-03-05 18:33:10 +01:00
Axel Chalon
7014642815 Implement parity_versionInfo & parity_setChain on LC; fix parity_setChain (#10312)
* Light client: implement parity_versionInfo RPC

* Light client: implement set_exit_handler & parity_setChain RPC

* parity_setChain RPC: return an error if failed (instead of `true`)

* Implement eth_subscribe('syncing') RPC for full node & light node

* Fix indentation

* Revert commit: Implement eth_subscribe('syncing')

* Revert change to Cr callback function
2019-03-04 20:24:53 +01:00
Denis S. Soldatov aka General-Beck
1bd4564216 CI publish to aws (#10446)
* move publish aws from gitlab.yml to gitlab scripts

* gitlab.yml cleaning
move publish AWS to gitlab scripts
remove dependencies from android build
2019-03-04 21:59:20 +03:00
Andrew Jones
97cb010df8 Silence Error::cause deprecations (#10438) 2019-03-02 13:18:18 +01:00
Hernando Castano
ed18c7b54c Use correct name for documentation field in Cargo.toml (#10440) 2019-03-01 16:23:40 +00:00
Thibaut Sardan
e71598d876 Update hardcoded headers for Foundation, Ropsten, Kovan and Classic (#10417)
* update foundation to #7262209

* update kovan to #10434561

* update ropsten to #5027841

* update classic to #7555073

* Update Ropsten headers to #5101569
2019-02-27 15:50:45 +01:00
Marek Kotewicz
3d0ce10fa6 panic_hook module uses eprintln instead of raw stderr interface (#10426) 2019-02-27 09:48:40 +00:00
soc1c
cfc8df156b ci: clean up gitlab-ci.yml leftovers from previous merge (#10429) 2019-02-27 10:47:27 +01:00
Marek Kotewicz
94cb3b6e0e fix underflow in pip, closes #10419 (#10423) 2019-02-27 10:08:04 +01:00
Marek Kotewicz
fefec000fb remove redundant macro println_stderr from parity/cli/usage.rs (#10425) 2019-02-27 10:07:41 +01:00
Mohanson
c7ded6a785 Remove duplicate test cases (#10385)
Case create_account() is same as new_account()
2019-02-27 10:07:12 +01:00
Marek Kotewicz
2fbb952cdd parity/main.rs uses eprintln instead of raw stderr interface (#10427) 2019-02-27 11:41:03 +03:00
Marek Kotewicz
e2ab3e4f5b fix panic when logging directory does not exist, closes #10420 (#10424) 2019-02-26 18:14:11 +01:00
elferdo
1871275ecd Refactor ethcore::client::TransactResult to use it inside std::result::Result (#10366)
* Refactor TransactResult

* Adapt evmbin and tests
2019-02-26 13:49:33 +01:00
joshua-mir
afc1b72611 10000 > 5000 (#10422)
addresses #10418
2019-02-26 15:35:40 +03:00
Niklas Adolfsson
c5c3fb6a75 fix(rpc-types): replace uint and hash with ethereum_types v0.4 (#10217)
* fix(rpc-types): remove uint and hash wrappers

* fix(tests)

* fix(cleanup)

* grumbles(rpc-api): revert `verify_signature`

* revert change of `U64` -> `u64`

* fix(cleanup after bad merge)

* chore(bump ethereum-types)

* fix(bad merge)

* feat(tests ethereum-types): add tests

* chore(update `ethereum-types` to 0.4.2)

* feat(tests for h256)

* chore(rpc): remove `ethbloom` import

Use re-export from `ethereum-types` instead

* fix(bad merge): remove `DefaultAccount` type

* doc(add TODO with issue link)
2019-02-25 14:27:28 +01:00
5chdn
bceb883d99 snap: reenable i386, arm64, armhf architecture publishing (#10386)
* snap: reenable i386, arm64, armhf architecture publishing

* gitlab: fix indent

* gitlab: fix yml syntax

* Linker for crosscomile

* fix target to linker

* new docker image

* fix lint, add build to this PR

* calc SHA3 using rhash

* add new images for i386, armhf

* show snap target & artifacts

* set CARGO_TARGET for publish snap

* move detect Version to publish snap

* rm libc6 dep from snap-template up pub-snap script

* clean up cargo config before add linker

* move linker config to docker images
2019-02-25 14:56:38 +03:00
Antoine
fcccbf3b75 fix #10390 (#10391) 2019-02-22 15:31:34 +01:00
Wei Tang
9ad71b7baa Fix to_pod storage trie value decoding (#10368) 2019-02-22 14:00:20 +01:00
TriplEight
4311d43497 revert some changes, could be buggy (#10399) 2019-02-21 21:06:49 +01:00
5chdn
0815cc3b83 version: bump nightly to 2.5 (#10392)
* version: bump nightly to 2.5

* revert(rand 0.3.22)
2019-02-21 20:03:34 +01:00
TriplEight
b21844b371 no-git for publish jobs, empty artifacts dir (#10393)
* no-git for publish jobs, empty artifacts dir

* fix syntax

* prettiness

* fix prettiness

* should get rid of git in publishing
2019-02-21 21:14:59 +03:00
Niklas Adolfsson
f825048efa fix(jni): bump to jni to 0.11 & remove unsafe impl (#10394) 2019-02-21 19:26:01 +03:00
Niklas Adolfsson
2cbffe36e2 chore(bump ethereum-types) (#10396)
Fixes a de-serialization bug in `ethereum-tyes`
2019-02-21 15:34:41 +00:00
220 changed files with 11364 additions and 12274 deletions

View File

@@ -4,11 +4,13 @@ stages:
- publish
- optional
image: parity/rust-parity-ethereum-build:xenial
image: parity/parity-ci-linux:latest
variables:
GIT_STRATEGY: fetch
GIT_SUBMODULE_STRATEGY: recursive
CI_SERVER_NAME: "GitLab CI"
CARGO_HOME: "/ci-cache/${CI_PROJECT_NAME}/cargo/${CI_JOB_NAME}"
SCCACHE_DIR: "/ci-cache/${CI_PROJECT_NAME}/sccache"
CARGO_TARGET: x86_64-unknown-linux-gnu
.no_git: &no_git # disable git strategy
@@ -30,41 +32,72 @@ variables:
expire_in: 1 mos
paths:
- artifacts/
- tools/
.docker-cache-status: &docker-cache-status
variables:
CARGO_HOME: "/cargo/${CI_JOB_NAME}"
CARGO_HOME: "/ci-cache/parity-ethereum/cargo/${CI_JOB_NAME}"
dependencies: []
before_script:
- SCCACHE_ERROR_LOG=/builds/parity/parity-ethereum/sccache_error.log RUST_LOG=sccache::server=debug sccache --start-server
- rustup show
- cargo --version
- SCCACHE_ERROR_LOG=/builds/parity/parity-ethereum/sccache_debug.log
RUST_LOG=sccache=debug
sccache --start-server
- sccache -s
after_script:
- echo "All crate-types:"
- grep 'parse_arguments.*--crate-type' sccache_error.log | sed -re 's/.*"--crate-type", "([^"]+)".*/\1/' | sort | uniq -c
- echo "Non-cacheable reasons:"
- grep CannotCache sccache_error.log | sed -re 's/.*CannotCache\((.+)\).*/\1/' | sort | uniq -c
# sccache debug info
- if test -e sccache_debug.log;
then
echo "_____All crate-types:_____";
grep 'parse_arguments.*--crate-type' sccache_debug.log | sed -re 's/.*"--crate-type", "([^"]+)".*/\1/' | sort | uniq -c;
echo "_____Non-cacheable reasons:_____";
grep CannotCache sccache_debug.log | sed -re 's/.*CannotCache\((.+)\).*/\1/' | sort | uniq -c;
else
echo "_____No logs from sccache_____";
exit 0;
fi
tags:
- linux-docker
.build-on-linux: &build-on-linux
stage: build
<<: *docker-cache-status
<<: *collect_artifacts
script:
- scripts/gitlab/build-linux.sh
- sccache -s
after_script:
- mkdir -p tools
- cp -r scripts/docker/hub/* ./tools
- cp scripts/gitlab/publish-snap.sh ./tools
- cp scripts/gitlab/publish-onchain.sh ./tools
- cp scripts/gitlab/safe-curl.sh ./tools
- echo v"$(sed -r -n '1,/^version/s/^version\s*=\s*"([^"]+)".*$/\1/p' Cargo.toml)" |
tee ./tools/VERSION
- echo "$(sed -r -n '1,/^track/s/^track\s*=\s*"([^"]+)".*$/\1/p' ./util/version/Cargo.toml)" |
tee ./tools/TRACK
cargo-check 0 3:
stage: test
<<: *docker-cache-status
script:
- time cargo check --target $CARGO_TARGET --locked --no-default-features
- time cargo check --target $CARGO_TARGET --locked --no-default-features --verbose --color=always
- sccache -s
cargo-check 1 3:
stage: test
<<: *docker-cache-status
script:
- time cargo check --target $CARGO_TARGET --locked --manifest-path util/io/Cargo.toml --no-default-features
- time cargo check --target $CARGO_TARGET --locked --manifest-path util/io/Cargo.toml --no-default-features --verbose --color=always
- sccache -s
cargo-check 2 3:
stage: test
<<: *docker-cache-status
script:
- time cargo check --target $CARGO_TARGET --locked --manifest-path util/io/Cargo.toml --features "mio"
- time cargo check --target $CARGO_TARGET --locked --manifest-path util/io/Cargo.toml --features "mio" --verbose --color=always
- sccache -s
cargo-audit:
@@ -72,7 +105,7 @@ cargo-audit:
<<: *docker-cache-status
script:
- cargo audit
- sccache -s
allow_failure: true # failed cargo audit shouldn't prevent a PR from being merged
validate-chainspecs:
stage: test
@@ -92,86 +125,114 @@ test-linux:
stage: build
<<: *docker-cache-status
script:
- ./scripts/gitlab/test-linux.sh
- ./scripts/gitlab/test-linux.sh stable
- sccache -s
build-android:
stage: build
image: parity/rust-android:gitlab-ci
variables:
CARGO_TARGET: armv7-linux-androideabi
script:
- scripts/gitlab/build-linux.sh
tags:
- linux-docker
<<: *collect_artifacts
build-linux: &build-linux
test-linux-beta:
stage: build
only: *releaseable_branches
<<: *docker-cache-status
script:
- scripts/gitlab/build-linux.sh
- ./scripts/gitlab/test-linux.sh beta
- sccache -s
<<: *collect_artifacts
test-linux-nightly:
stage: build
only: *releaseable_branches
<<: *docker-cache-status
script:
- ./scripts/gitlab/test-linux.sh nightly
- sccache -s
allow_failure: true
build-android:
<<: *build-on-linux
image: parity/rust-parity-ethereum-android-build:stretch
variables:
CARGO_TARGET: armv7-linux-androideabi
build-linux:
<<: *build-on-linux
only: *releaseable_branches
build-linux-i386:
<<: *build-linux
<<: *build-on-linux
only: *releaseable_branches
image: parity/rust-parity-ethereum-build:i386
variables:
CARGO_TARGET: i686-unknown-linux-gnu
build-linux-arm64:
<<: *build-linux
<<: *build-on-linux
only: *releaseable_branches
image: parity/rust-parity-ethereum-build:arm64
variables:
CARGO_TARGET: aarch64-unknown-linux-gnu
build-linux-armhf:
<<: *build-linux
<<: *build-on-linux
only: *releaseable_branches
image: parity/rust-parity-ethereum-build:armhf
variables:
CARGO_TARGET: armv7-unknown-linux-gnueabihf
build-darwin:
stage: build
<<: *collect_artifacts
only: *releaseable_branches
variables:
CARGO_TARGET: x86_64-apple-darwin
CARGO_HOME: "${CI_PROJECT_DIR}/.cargo"
CARGO_HOME: "${CI_PROJECT_DIR}/.cargo"
CC: gcc
CXX: g++
script:
- scripts/gitlab/build-linux.sh
tags:
- rust-osx
<<: *collect_artifacts
build-windows:
stage: build
<<: *collect_artifacts
only: *releaseable_branches
variables:
CARGO_TARGET: x86_64-pc-windows-msvc
CARGO_HOME: "${CI_PROJECT_DIR}/.cargo"
CARGO_HOME: "C:/ci-cache/parity-ethereum/cargo/$CI_JOB_NAME"
GIT_SUBMODULE_STRATEGY: none
script:
- sh scripts/gitlab/build-windows.sh
tags:
- rust-windows
<<: *collect_artifacts
publish-docker:
stage: publish
<<: *no_git
only: *releaseable_branches
cache: {}
except:
variables:
- $SCHEDULE_TAG == "nightly"
dependencies:
- build-linux
tags:
- shell
environment:
name: parity-build
cache: {}
image: docker:stable
services:
- docker:dind
variables:
DOCKER_HOST: tcp://localhost:2375
DOCKER_DRIVER: overlay2
GIT_STRATEGY: none
# DOCKERFILE: tools/Dockerfile
# CONTAINER_IMAGE: parity/parity
script:
- scripts/gitlab/publish-docker.sh parity
# we stopped pushing nightlies to dockerhub, will push to own registry prb.
- ./tools/publish-docker.sh
tags:
- kubernetes-parity-build
publish-snap: &publish-snap
stage: publish
<<: *no_git
only: *releaseable_branches
image: snapcore/snapcraft
variables:
@@ -182,13 +243,13 @@ publish-snap: &publish-snap
tags:
- linux-docker
script:
- scripts/gitlab/publish-snap.sh
<<: *collect_artifacts
- ./tools/publish-snap.sh
publish-snap-i386:
<<: *publish-snap
variables:
BUILD_ARCH: i386
CARGO_TARGET: i686-unknown-linux-gnu
dependencies:
- build-linux-i386
@@ -196,6 +257,7 @@ publish-snap-arm64:
<<: *publish-snap
variables:
BUILD_ARCH: arm64
CARGO_TARGET: aarch64-unknown-linux-gnu
dependencies:
- build-linux-arm64
@@ -203,11 +265,13 @@ publish-snap-armhf:
<<: *publish-snap
variables:
BUILD_ARCH: armhf
CARGO_TARGET: armv7-unknown-linux-gnueabihf
dependencies:
- build-linux-armhf
publish-onchain:
stage: publish
<<: *no_git
only: *releaseable_branches
cache: {}
dependencies:
@@ -215,7 +279,7 @@ publish-onchain:
- build-darwin
- build-windows
script:
- scripts/gitlab/publish-onchain.sh
- ./tools/publish-onchain.sh
tags:
- linux-docker
@@ -247,14 +311,15 @@ publish-awss3-release:
publish-docs:
stage: publish
# <<: *no_git
image: parity/rust-parity-ethereum-docs:xenial
only:
- tags
except:
- nightly
cache: {}
dependencies: []
script:
- scripts/gitlab/publish-docs.sh
tags:
- linux-docker
allow_failure: true

View File

@@ -1,162 +1,152 @@
## Parity-Ethereum [v2.3.0](https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.0) (2019-01-16)
## Parity-Ethereum [v2.4.3](https://github.com/paritytech/parity-ethereum/releases/tag/v2.4.3) (2019-03-22)
Parity-Ethereum 2.3.0-beta is a consensus-relevant security release that reverts Constantinople on the Ethereum network. Upgrading is mandatory for Ethereum, and strongly recommended for other networks.
- **Consensus** - Ethereum Network: Pull Constantinople protocol upgrade on Ethereum (#10189)
- Read more: [Security Alert: Ethereum Constantinople Postponement](https://blog.ethereum.org/2019/01/15/security-alert-ethereum-constantinople-postponement/)
- **Networking** - All networks: Ping nodes from discovery (#10167)
- **Wasm** - Kovan Network: Update pwasm-utils to 0.6.1 (#10134)
Other notable changes:
- Existing blocks in the database are now kept when restoring a Snapshot. (#8643)
- Block and transaction propagation is improved significantly. (#9954)
- The ERC-191 Signed Data Standard is now supported by `personal_sign191`. (#9701)
- Add support for ERC-191/712 `eth_signTypedData` as a standard for machine-verifiable and human-readable typed data signing with Ethereum keys. (#9631)
- Add support for ERC-1186 `eth_getProof` (#9001)
- Add experimental RPCs flag to enable ERC-191, ERC-712, and ERC-1186 APIs via `--jsonrpc-experimental` (#9928)
- Make `CALLCODE` to trace value to be the code address. (#9881)
Configuration changes:
- The EIP-98 transition is now disabled by default. If you previously had no `eip98transition` specified in your chain specification, you would enable this now manually on block `0x0`. (#9955)
- Also, unknown fields in chain specs are now rejected. (#9972)
- The Tendermint engine was removed from Parity Ethereum and is no longer available and maintained. (#9980)
- Ropsten testnet data and keys moved from `test/` to `ropsten/` subdir. To reuse your old keys and data either copy or symlink them to the new location. (#10123)
- Strict empty steps validation (#10041)
- If you have a chain with`empty_steps` already running, some blocks most likely contain non-strict entries (unordered or duplicated empty steps). In this release `strict_empty_steps_transition` is enabled by default at block `0x0` for any chain with `empty_steps`.
- If your network uses `empty_steps` you **must** (A) plan a hard fork and change `strict_empty_steps_transition` to the desired fork block and (B) update the clients of the whole network to 2.2.7-stable / 2.3.0-beta. If for some reason you don't want to do this please set`strict_empty_steps_transition` to `0xfffffffff` to disable it.
_Note:_ This release marks Parity 2.3 as _beta_. All versions of Parity 2.2 are now considered _stable_.
Parity-Ethereum 2.4.3-beta is a bugfix release that improves performance and stability. This patch release contains a critical bug fix where serving light clients previously led to client crashes. Upgrading is highly recommended.
The full list of included changes:
- 2.4.3 beta backports ([#10508](https://github.com/paritytech/parity-ethereum/pull/10508))
- Version: bump beta
- Add additional request tests ([#10503](https://github.com/paritytech/parity-ethereum/pull/10503))
- Backports for 2.3.0 beta ([#10164](https://github.com/paritytech/parity-ethereum/pull/10164))
- Snap: fix path in script ([#10157](https://github.com/paritytech/parity-ethereum/pull/10157))
- Make sure parent block is not in importing queue when importing ancient blocks ([#10138](https://github.com/paritytech/parity-ethereum/pull/10138))
- Ci: re-enable snap publishing ([#10142](https://github.com/paritytech/parity-ethereum/pull/10142))
- Hf in POA Core (2019-01-18) - Constantinople ([#10155](https://github.com/paritytech/parity-ethereum/pull/10155))
- Update EWF's tobalaba chainspec ([#10152](https://github.com/paritytech/parity-ethereum/pull/10152))
- Replace ethcore-logger with env-logger. ([#10102](https://github.com/paritytech/parity-ethereum/pull/10102))
- Finality: dont require chain head to be in the chain ([#10054](https://github.com/paritytech/parity-ethereum/pull/10054))
- Remove caching for node connections ([#10143](https://github.com/paritytech/parity-ethereum/pull/10143))
- Blooms file iterator empty on out of range position. ([#10145](https://github.com/paritytech/parity-ethereum/pull/10145))
- Autogen docs for the "Configuring Parity Ethereum" wiki page. ([#10067](https://github.com/paritytech/parity-ethereum/pull/10067))
- Misc: bump license header to 2019 ([#10135](https://github.com/paritytech/parity-ethereum/pull/10135))
- Hide most of the logs from cpp example. ([#10139](https://github.com/paritytech/parity-ethereum/pull/10139))
- Don't try to send oversized packets ([#10042](https://github.com/paritytech/parity-ethereum/pull/10042))
- Private tx enabled flag added into STATUS packet ([#9999](https://github.com/paritytech/parity-ethereum/pull/9999))
- Update pwasm-utils to 0.6.1 ([#10134](https://github.com/paritytech/parity-ethereum/pull/10134))
- Extract blockchain from ethcore ([#10114](https://github.com/paritytech/parity-ethereum/pull/10114))
- Ethcore: update hardcoded headers ([#10123](https://github.com/paritytech/parity-ethereum/pull/10123))
- Identity fix ([#10128](https://github.com/paritytech/parity-ethereum/pull/10128))
- Use LenCachingMutex to optimize verification. ([#10117](https://github.com/paritytech/parity-ethereum/pull/10117))
- Pyethereum keystore support ([#9710](https://github.com/paritytech/parity-ethereum/pull/9710))
- Bump rocksdb-sys to 0.5.5 ([#10124](https://github.com/paritytech/parity-ethereum/pull/10124))
- Parity-clib: `async C bindings to RPC requests` + `subscribe/unsubscribe to websocket events` ([#9920](https://github.com/paritytech/parity-ethereum/pull/9920))
- Refactor (hardware wallet) : reduce the number of threads ([#9644](https://github.com/paritytech/parity-ethereum/pull/9644))
- Hf in POA Sokol (2019-01-04) ([#10077](https://github.com/paritytech/parity-ethereum/pull/10077))
- Fix broken links ([#10119](https://github.com/paritytech/parity-ethereum/pull/10119))
- Follow-up to [#10105](https://github.com/paritytech/parity-ethereum/issues/10105) ([#10107](https://github.com/paritytech/parity-ethereum/pull/10107))
- Move EIP-712 crate back to parity-ethereum ([#10106](https://github.com/paritytech/parity-ethereum/pull/10106))
- Move a bunch of stuff around ([#10101](https://github.com/paritytech/parity-ethereum/pull/10101))
- Revert "Add --frozen when running cargo ([#10081](https://github.com/paritytech/parity-ethereum/pull/10081))" ([#10105](https://github.com/paritytech/parity-ethereum/pull/10105))
- Fix left over small grumbles on whitespaces ([#10084](https://github.com/paritytech/parity-ethereum/pull/10084))
- Add --frozen when running cargo ([#10081](https://github.com/paritytech/parity-ethereum/pull/10081))
- Fix pubsub new_blocks notifications to include all blocks ([#9987](https://github.com/paritytech/parity-ethereum/pull/9987))
- Update some dependencies for compilation with pc-windows-gnu ([#10082](https://github.com/paritytech/parity-ethereum/pull/10082))
- Fill transaction hash on ethGetLog of light client. ([#9938](https://github.com/paritytech/parity-ethereum/pull/9938))
- Update changelog update for 2.2.5-beta and 2.1.10-stable ([#10064](https://github.com/paritytech/parity-ethereum/pull/10064))
- Implement len caching for parking_lot RwLock ([#10032](https://github.com/paritytech/parity-ethereum/pull/10032))
- Update parking_lot to 0.7 ([#10050](https://github.com/paritytech/parity-ethereum/pull/10050))
- Bump crossbeam. ([#10048](https://github.com/paritytech/parity-ethereum/pull/10048))
- Ethcore: enable constantinople on ethereum ([#10031](https://github.com/paritytech/parity-ethereum/pull/10031))
- Strict empty steps validation ([#10041](https://github.com/paritytech/parity-ethereum/pull/10041))
- Center the Subtitle, use some CAPS ([#10034](https://github.com/paritytech/parity-ethereum/pull/10034))
- Change test miner max memory to malloc reports. ([#10024](https://github.com/paritytech/parity-ethereum/pull/10024))
- Sort the storage for private state ([#10018](https://github.com/paritytech/parity-ethereum/pull/10018))
- Fix: test corpus_inaccessible panic ([#10019](https://github.com/paritytech/parity-ethereum/pull/10019))
- Ci: move future releases to ethereum subdir on s3 ([#10017](https://github.com/paritytech/parity-ethereum/pull/10017))
- Light(on_demand): decrease default time window to 10 secs ([#10016](https://github.com/paritytech/parity-ethereum/pull/10016))
- Light client : failsafe crate (circuit breaker) ([#9790](https://github.com/paritytech/parity-ethereum/pull/9790))
- Lencachingmutex ([#9988](https://github.com/paritytech/parity-ethereum/pull/9988))
- Version and notification for private contract wrapper added ([#9761](https://github.com/paritytech/parity-ethereum/pull/9761))
- Handle failing case for update account cache in require ([#9989](https://github.com/paritytech/parity-ethereum/pull/9989))
- Add tokio runtime to ethcore io worker ([#9979](https://github.com/paritytech/parity-ethereum/pull/9979))
- Move daemonize before creating account provider ([#10003](https://github.com/paritytech/parity-ethereum/pull/10003))
- Docs: update changelogs ([#9990](https://github.com/paritytech/parity-ethereum/pull/9990))
- Fix daemonize ([#10000](https://github.com/paritytech/parity-ethereum/pull/10000))
- Fix Bloom migration ([#9992](https://github.com/paritytech/parity-ethereum/pull/9992))
- Remove tendermint engine support ([#9980](https://github.com/paritytech/parity-ethereum/pull/9980))
- Calculate gas for deployment transaction ([#9840](https://github.com/paritytech/parity-ethereum/pull/9840))
- Fix unstable peers and slowness in sync ([#9967](https://github.com/paritytech/parity-ethereum/pull/9967))
- Adds parity_verifySignature RPC method ([#9507](https://github.com/paritytech/parity-ethereum/pull/9507))
- Improve block and transaction propagation ([#9954](https://github.com/paritytech/parity-ethereum/pull/9954))
- Deny unknown fields for chainspec ([#9972](https://github.com/paritytech/parity-ethereum/pull/9972))
- Fix docker build ([#9971](https://github.com/paritytech/parity-ethereum/pull/9971))
- Ci: rearrange pipeline by logic ([#9970](https://github.com/paritytech/parity-ethereum/pull/9970))
- Add changelogs for 2.0.9, 2.1.4, 2.1.6, and 2.2.1 ([#9963](https://github.com/paritytech/parity-ethereum/pull/9963))
- Add Error message when sync is still in progress. ([#9475](https://github.com/paritytech/parity-ethereum/pull/9475))
- Make CALLCODE to trace value to be the code address ([#9881](https://github.com/paritytech/parity-ethereum/pull/9881))
- Fix light client informant while syncing ([#9932](https://github.com/paritytech/parity-ethereum/pull/9932))
- Add a optional json dump state to evm-bin ([#9706](https://github.com/paritytech/parity-ethereum/pull/9706))
- Disable EIP-98 transition by default ([#9955](https://github.com/paritytech/parity-ethereum/pull/9955))
- Remove secret_store runtimes. ([#9888](https://github.com/paritytech/parity-ethereum/pull/9888))
- Fix a deadlock ([#9952](https://github.com/paritytech/parity-ethereum/pull/9952))
- Chore(eip712): remove unused `failure-derive` ([#9958](https://github.com/paritytech/parity-ethereum/pull/9958))
- Do not use the home directory as the working dir in docker ([#9834](https://github.com/paritytech/parity-ethereum/pull/9834))
- Prevent silent errors in daemon mode, closes [#9367](https://github.com/paritytech/parity-ethereum/issues/9367) ([#9946](https://github.com/paritytech/parity-ethereum/pull/9946))
- Fix empty steps ([#9939](https://github.com/paritytech/parity-ethereum/pull/9939))
- Adjust requests costs for light client ([#9925](https://github.com/paritytech/parity-ethereum/pull/9925))
- Eip-1186: add `eth_getProof` RPC-Method ([#9001](https://github.com/paritytech/parity-ethereum/pull/9001))
- Missing blocks in filter_changes RPC ([#9947](https://github.com/paritytech/parity-ethereum/pull/9947))
- Allow rust-nightly builds fail in nightly builds ([#9944](https://github.com/paritytech/parity-ethereum/pull/9944))
- Update eth-secp256k1 to include fix for BSDs ([#9935](https://github.com/paritytech/parity-ethereum/pull/9935))
- Unbreak build on rust -stable ([#9934](https://github.com/paritytech/parity-ethereum/pull/9934))
- Keep existing blocks when restoring a Snapshot ([#8643](https://github.com/paritytech/parity-ethereum/pull/8643))
- Add experimental RPCs flag ([#9928](https://github.com/paritytech/parity-ethereum/pull/9928))
- Clarify poll lifetime ([#9922](https://github.com/paritytech/parity-ethereum/pull/9922))
- Docs(require rust 1.30) ([#9923](https://github.com/paritytech/parity-ethereum/pull/9923))
- Use block header for building finality ([#9914](https://github.com/paritytech/parity-ethereum/pull/9914))
- Simplify cargo audit ([#9918](https://github.com/paritytech/parity-ethereum/pull/9918))
- Light-fetch: Differentiate between out-of-gas/manual throw and use required gas from response on failure ([#9824](https://github.com/paritytech/parity-ethereum/pull/9824))
- Eip 191 ([#9701](https://github.com/paritytech/parity-ethereum/pull/9701))
- Fix(logger): `reqwest` no longer a dependency ([#9908](https://github.com/paritytech/parity-ethereum/pull/9908))
- Remove rust-toolchain file ([#9906](https://github.com/paritytech/parity-ethereum/pull/9906))
- Foundation: 6692865, ropsten: 4417537, kovan: 9363457 ([#9907](https://github.com/paritytech/parity-ethereum/pull/9907))
- Ethcore: use Machine::verify_transaction on parent block ([#9900](https://github.com/paritytech/parity-ethereum/pull/9900))
- Chore(rpc-tests): remove unused rand ([#9896](https://github.com/paritytech/parity-ethereum/pull/9896))
- Fix: Intermittent failing CI due to addr in use ([#9885](https://github.com/paritytech/parity-ethereum/pull/9885))
- Chore(bump docopt): 0.8 -> 1.0 ([#9889](https://github.com/paritytech/parity-ethereum/pull/9889))
- Use expect ([#9883](https://github.com/paritytech/parity-ethereum/pull/9883))
- Use Weak reference in PubSubClient ([#9886](https://github.com/paritytech/parity-ethereum/pull/9886))
- Ci: nuke the gitlab caches ([#9855](https://github.com/paritytech/parity-ethereum/pull/9855))
- Remove unused code ([#9884](https://github.com/paritytech/parity-ethereum/pull/9884))
- Fix json tracer overflow ([#9873](https://github.com/paritytech/parity-ethereum/pull/9873))
- Allow to seal work on latest block ([#9876](https://github.com/paritytech/parity-ethereum/pull/9876))
- Fix docker script ([#9854](https://github.com/paritytech/parity-ethereum/pull/9854))
- Health endpoint ([#9847](https://github.com/paritytech/parity-ethereum/pull/9847))
- Gitlab-ci: make android release build succeed ([#9743](https://github.com/paritytech/parity-ethereum/pull/9743))
- Clean up existing benchmarks ([#9839](https://github.com/paritytech/parity-ethereum/pull/9839))
- Update Callisto block reward code to support HF1 ([#9811](https://github.com/paritytech/parity-ethereum/pull/9811))
- Option to disable keep alive for JSON-RPC http transport ([#9848](https://github.com/paritytech/parity-ethereum/pull/9848))
- Classic.json Bootnode Update ([#9828](https://github.com/paritytech/parity-ethereum/pull/9828))
- Support MIX. ([#9767](https://github.com/paritytech/parity-ethereum/pull/9767))
- Ci: remove failing tests for android, windows, and macos ([#9788](https://github.com/paritytech/parity-ethereum/pull/9788))
- Implement NoProof for json tests and update tests reference (replaces [#9744](https://github.com/paritytech/parity-ethereum/issues/9744)) ([#9814](https://github.com/paritytech/parity-ethereum/pull/9814))
- Chore(bump regex) ([#9842](https://github.com/paritytech/parity-ethereum/pull/9842))
- Ignore global cache for patched accounts ([#9752](https://github.com/paritytech/parity-ethereum/pull/9752))
- Move state root verification before gas used ([#9841](https://github.com/paritytech/parity-ethereum/pull/9841))
- Fix(docker-aarch64) : cross-compile config ([#9798](https://github.com/paritytech/parity-ethereum/pull/9798))
- Version: bump nightly to 2.3.0 ([#9819](https://github.com/paritytech/parity-ethereum/pull/9819))
- Tests modification for windows CI ([#9671](https://github.com/paritytech/parity-ethereum/pull/9671))
- Eip-712 implementation ([#9631](https://github.com/paritytech/parity-ethereum/pull/9631))
- Fix typo ([#9826](https://github.com/paritytech/parity-ethereum/pull/9826))
- Clean up serde rename and use rename_all = camelCase when possible ([#9823](https://github.com/paritytech/parity-ethereum/pull/9823))
## Parity-Ethereum [v2.4.2](https://github.com/paritytech/parity-ethereum/releases/tag/v2.4.2) (2019-03-20)
Parity-Ethereum 2.4.2-beta is a bugfix release that improves performance and stability.
The full list of included changes:
- 2.4.2 beta backports ([#10488](https://github.com/paritytech/parity-ethereum/pull/10488))
- Version: bump beta
- Сaching through docker volume ([#10477](https://github.com/paritytech/parity-ethereum/pull/10477))
- fix win&mac build ([#10486](https://github.com/paritytech/parity-ethereum/pull/10486))
- fix(extract `timestamp_checked_add` as lib) ([#10383](https://github.com/paritytech/parity-ethereum/pull/10383))
## Parity-Ethereum [v2.4.1](https://github.com/paritytech/parity-ethereum/releases/tag/v2.4.1) (2019-03-19)
Parity-Ethereum 2.4.1-beta is a bugfix release that improves performance and stability.
The full list of included changes:
- 2.4.1 beta backports ([#10471](https://github.com/paritytech/parity-ethereum/pull/10471))
- Version: bump beta
- Implement parity_versionInfo & parity_setChain on LC; fix parity_setChain ([#10312](https://github.com/paritytech/parity-ethereum/pull/10312))
- CI publish to aws ([#10446](https://github.com/paritytech/parity-ethereum/pull/10446))
- CI aws git checkout ([#10451](https://github.com/paritytech/parity-ethereum/pull/10451))
- Revert "CI aws git checkout ([#10451](https://github.com/paritytech/parity-ethereum/pull/10451))" ([#10456](https://github.com/paritytech/parity-ethereum/pull/10456))
- Tests parallelized ([#10452](https://github.com/paritytech/parity-ethereum/pull/10452))
- Ensure static validator set changes are recognized ([#10467](https://github.com/paritytech/parity-ethereum/pull/10467))
## Parity-Ethereum [v2.4.0](https://github.com/paritytech/parity-ethereum/releases/tag/v2.4.0) (2019-02-25)
Parity-Ethereum 2.4.0-beta is our trifortnightly minor version release coming with a lot of new features as well as bugfixes and performance improvements.
Notable changes:
- Account management is now deprecated ([#10213](https://github.com/paritytech/parity-ethereum/pull/10213))
- Local accounts can now be specified via CLI ([#9960](https://github.com/paritytech/parity-ethereum/pull/9960))
- Chains can now be reset to a particular block via CLI ([#9782](https://github.com/paritytech/parity-ethereum/pull/9782))
- Ethash now additionally implements ProgPoW ([#9762](https://github.com/paritytech/parity-ethereum/pull/9762))
- The `eip1283DisableTransition` flag was added to revert EIP-1283 ([#10214](https://github.com/paritytech/parity-ethereum/pull/10214))
The full list of included changes:
- More Backports for Beta 2.4.0 ([#10431](https://github.com/paritytech/parity-ethereum/pull/10431))
- Revert some changes, could be buggy ([#10399](https://github.com/paritytech/parity-ethereum/pull/10399))
- Ci: clean up gitlab-ci.yml leftovers from previous merge ([#10429](https://github.com/paritytech/parity-ethereum/pull/10429))
- 10000 > 5000 ([#10422](https://github.com/paritytech/parity-ethereum/pull/10422))
- Fix underflow in pip, closes [#10419](https://github.com/paritytech/parity-ethereum/pull/10419) ([#10423](https://github.com/paritytech/parity-ethereum/pull/10423))
- Fix panic when logging directory does not exist, closes [#10420](https://github.com/paritytech/parity-ethereum/pull/10420) ([#10424](https://github.com/paritytech/parity-ethereum/pull/10424))
- Update hardcoded headers for Foundation, Ropsten, Kovan and Classic ([#10417](https://github.com/paritytech/parity-ethereum/pull/10417))
- Backports for Beta 2.4.0 ([#10416](https://github.com/paritytech/parity-ethereum/pull/10416))
- No-git for publish jobs, empty artifacts dir ([#10393](https://github.com/paritytech/parity-ethereum/pull/10393))
- Snap: reenable i386, arm64, armhf architecture publishing ([#10386](https://github.com/paritytech/parity-ethereum/pull/10386))
- Tx pool: always accept local transactions ([#10375](https://github.com/paritytech/parity-ethereum/pull/10375))
- Fix to_pod storage trie value decoding ([#10368](https://github.com/paritytech/parity-ethereum/pull/10368))
- Version: mark 2.4.0 beta
- Update to latest mem-db, hash-db and trie-db. ([#10314](https://github.com/paritytech/parity-ethereum/pull/10314))
- Tx pool: always accept local transactions ([#10375](https://github.com/paritytech/parity-ethereum/pull/10375))
- Fix(trace_main! macro): don't re-export ([#10384](https://github.com/paritytech/parity-ethereum/pull/10384))
- Exchanged old(azure) bootnodes with new(ovh) ones ([#10309](https://github.com/paritytech/parity-ethereum/pull/10309))
- Ethash: implement Progpow ([#9762](https://github.com/paritytech/parity-ethereum/pull/9762))
- Snap: add the removable-media plug ([#10377](https://github.com/paritytech/parity-ethereum/pull/10377))
- Add message to IO errors ([#10324](https://github.com/paritytech/parity-ethereum/pull/10324))
- Chore(bump parity-daemonize): require rust >= 1.31 ([#10359](https://github.com/paritytech/parity-ethereum/pull/10359))
- Secretstore: use in-memory transport in cluster tests ([#9850](https://github.com/paritytech/parity-ethereum/pull/9850))
- Add fields to `memzero`'s Cargo.toml ([#10362](https://github.com/paritytech/parity-ethereum/pull/10362))
- Snap: release untagged versions from branches to the candidate snap channel ([#10357](https://github.com/paritytech/parity-ethereum/pull/10357))
- Fix(compilation warns): `no-default-features` ([#10346](https://github.com/paritytech/parity-ethereum/pull/10346))
- No volumes are needed, just run -v volume:/path/in/the/container ([#10345](https://github.com/paritytech/parity-ethereum/pull/10345))
- Fixed misstype ([#10351](https://github.com/paritytech/parity-ethereum/pull/10351))
- Snap: prefix version and populate candidate channel ([#10343](https://github.com/paritytech/parity-ethereum/pull/10343))
- Bundle protocol and packet_id together in chain sync ([#10315](https://github.com/paritytech/parity-ethereum/pull/10315))
- Role back docker build image and docker deploy image to ubuntu:xenial… ([#10338](https://github.com/paritytech/parity-ethereum/pull/10338))
- Change docker image based on debian instead of ubuntu due to the chan… ([#10336](https://github.com/paritytech/parity-ethereum/pull/10336))
- Don't add discovery initiators to the node table ([#10305](https://github.com/paritytech/parity-ethereum/pull/10305))
- Fix(docker): fix not receives SIGINT ([#10059](https://github.com/paritytech/parity-ethereum/pull/10059))
- Snap: official image / test ([#10168](https://github.com/paritytech/parity-ethereum/pull/10168))
- Fix(add helper for timestamp overflows) ([#10330](https://github.com/paritytech/parity-ethereum/pull/10330))
- Additional error for invalid gas ([#10327](https://github.com/paritytech/parity-ethereum/pull/10327))
- Revive parity_setMinGasPrice RPC call ([#10294](https://github.com/paritytech/parity-ethereum/pull/10294))
- Add Statetest support for Constantinople Fix ([#10323](https://github.com/paritytech/parity-ethereum/pull/10323))
- Fix(parity-clib): grumbles that were not addressed in [#9920](https://github.com/paritytech/parity-ethereum/pull/9920) ([#10154](https://github.com/paritytech/parity-ethereum/pull/10154))
- Fix(light-rpc): Make `light_sync` generic ([#10238](https://github.com/paritytech/parity-ethereum/pull/10238))
- Fix publish job ([#10317](https://github.com/paritytech/parity-ethereum/pull/10317))
- Secure WS-RPC: grant access to all apis ([#10246](https://github.com/paritytech/parity-ethereum/pull/10246))
- Make specification of protocol in SyncRequester::send_request explicit ([#10295](https://github.com/paritytech/parity-ethereum/pull/10295))
- Fix: parity-clib/examples/cpp/CMakeLists.txt ([#10313](https://github.com/paritytech/parity-ethereum/pull/10313))
- Ci optimizations ([#10297](https://github.com/paritytech/parity-ethereum/pull/10297))
- Increase number of requested block bodies in chain sync ([#10247](https://github.com/paritytech/parity-ethereum/pull/10247))
- Deprecate account management ([#10213](https://github.com/paritytech/parity-ethereum/pull/10213))
- Properly handle check_epoch_end_signal errors ([#10015](https://github.com/paritytech/parity-ethereum/pull/10015))
- Fix(osx and windows builds): bump parity-daemonize ([#10291](https://github.com/paritytech/parity-ethereum/pull/10291))
- Add missing step for Using `systemd` service file ([#10175](https://github.com/paritytech/parity-ethereum/pull/10175))
- Call private contract methods from another private contract (read-onl… ([#10086](https://github.com/paritytech/parity-ethereum/pull/10086))
- Update ring to 0.14 ([#10262](https://github.com/paritytech/parity-ethereum/pull/10262))
- Fix(secret-store): deprecation warning ([#10301](https://github.com/paritytech/parity-ethereum/pull/10301))
- Update to jsonrpc-derive 10.0.2, fixes aliases bug ([#10300](https://github.com/paritytech/parity-ethereum/pull/10300))
- Convert to jsonrpc-derive, use jsonrpc-* from crates.io ([#10298](https://github.com/paritytech/parity-ethereum/pull/10298))
- Fix Windows build ([#10284](https://github.com/paritytech/parity-ethereum/pull/10284))
- Don't run the CPP example on CI ([#10285](https://github.com/paritytech/parity-ethereum/pull/10285))
- Additional tests for uint deserialization. ([#10279](https://github.com/paritytech/parity-ethereum/pull/10279))
- Prevent silent errors in daemon mode ([#10007](https://github.com/paritytech/parity-ethereum/pull/10007))
- Fix join-set test to be deterministic. ([#10263](https://github.com/paritytech/parity-ethereum/pull/10263))
- Update CHANGELOG-2.2.md ([#10254](https://github.com/paritytech/parity-ethereum/pull/10254))
- Macos heapsize force jemalloc ([#10234](https://github.com/paritytech/parity-ethereum/pull/10234))
- Allow specifying local accounts via CLI ([#9960](https://github.com/paritytech/parity-ethereum/pull/9960))
- Take in account zero gas price certification when doing transact_cont… ([#10232](https://github.com/paritytech/parity-ethereum/pull/10232))
- Update CHANGELOG.md ([#10249](https://github.com/paritytech/parity-ethereum/pull/10249))
- Fix typo: CHANGELOG-2.1 -> CHANGELOG-2.2 ([#10233](https://github.com/paritytech/parity-ethereum/pull/10233))
- Update copyright year to 2019. ([#10181](https://github.com/paritytech/parity-ethereum/pull/10181))
- Fixed: types::transaction::SignedTransaction; ([#10229](https://github.com/paritytech/parity-ethereum/pull/10229))
- Fix(ManageNetwork): replace Range with RangeInclusive ([#10209](https://github.com/paritytech/parity-ethereum/pull/10209))
- Import rpc transactions sequentially ([#10051](https://github.com/paritytech/parity-ethereum/pull/10051))
- Enable St-Peters-Fork ("Constantinople Fix") ([#10223](https://github.com/paritytech/parity-ethereum/pull/10223))
- Add EIP-1283 disable transition ([#10214](https://github.com/paritytech/parity-ethereum/pull/10214))
- Echo CORS request headers by default ([#10221](https://github.com/paritytech/parity-ethereum/pull/10221))
- Happy New Year! ([#10211](https://github.com/paritytech/parity-ethereum/pull/10211))
- Perform stripping during build ([#10208](https://github.com/paritytech/parity-ethereum/pull/10208))
- Remove CallContract and RegistryInfo re-exports from `ethcore/client` ([#10205](https://github.com/paritytech/parity-ethereum/pull/10205))
- Extract CallContract and RegistryInfo traits into their own crate ([#10178](https://github.com/paritytech/parity-ethereum/pull/10178))
- Update the changelogs for 2.1.11, 2.2.6, 2.2.7, and 2.3.0 ([#10197](https://github.com/paritytech/parity-ethereum/pull/10197))
- Cancel Constantinople HF on POA Core ([#10198](https://github.com/paritytech/parity-ethereum/pull/10198))
- Adds cli interface to allow reseting chain to a particular block ([#9782](https://github.com/paritytech/parity-ethereum/pull/9782))
- Run all `igd` methods in its own thread ([#10195](https://github.com/paritytech/parity-ethereum/pull/10195))
- Pull constantinople on ethereum network ([#10189](https://github.com/paritytech/parity-ethereum/pull/10189))
- Update for Android cross-compilation. ([#10180](https://github.com/paritytech/parity-ethereum/pull/10180))
- Version: bump fork blocks for kovan and foundation ([#10186](https://github.com/paritytech/parity-ethereum/pull/10186))
- Handle the case for contract creation on an empty but exist account w… ([#10065](https://github.com/paritytech/parity-ethereum/pull/10065))
- Align personal_unlockAccount behaviour when permanent unlock is disab… ([#10060](https://github.com/paritytech/parity-ethereum/pull/10060))
- Drop `runtime` after others (especially `ws_server`) ([#10179](https://github.com/paritytech/parity-ethereum/pull/10179))
- Version: bump nightly to 2.4 ([#10165](https://github.com/paritytech/parity-ethereum/pull/10165))
- Skip locking in statedb for non-canon blocks ([#10141](https://github.com/paritytech/parity-ethereum/pull/10141))
- Remove reference to ui-interface command-line option ([#10170](https://github.com/paritytech/parity-ethereum/pull/10170))
- Fix [#9822](https://github.com/paritytech/parity-ethereum/pull/9822): trace_filter does not return failed contract creation ([#10140](https://github.com/paritytech/parity-ethereum/pull/10140))
- Fix _cannot recursively call into `Core`_ issue ([#10144](https://github.com/paritytech/parity-ethereum/pull/10144))
- Fix(whisper): correct PoW calculation ([#10166](https://github.com/paritytech/parity-ethereum/pull/10166))
- Bump JSON-RPC ([#10151](https://github.com/paritytech/parity-ethereum/pull/10151))
- Ping nodes from discovery ([#10167](https://github.com/paritytech/parity-ethereum/pull/10167))
- Fix(android): remove dependency to libusb ([#10161](https://github.com/paritytech/parity-ethereum/pull/10161))
- Refactor(trim_right_matches -> trim_end_matches) ([#10159](https://github.com/paritytech/parity-ethereum/pull/10159))
- Merge Machine and WithRewards ([#10071](https://github.com/paritytech/parity-ethereum/pull/10071))
## Previous releases
- [CHANGELOG-2.2](docs/CHANGELOG-2.2.md) (_stable_)
- [CHANGELOG-2.3](docs/CHANGELOG-2.3.md) (_stable_)
- [CHANGELOG-2.2](docs/CHANGELOG-2.2.md) (EOL: 2019-02-25)
- [CHANGELOG-2.1](docs/CHANGELOG-2.1.md) (EOL: 2019-01-16)
- [CHANGELOG-2.0](docs/CHANGELOG-2.0.md) (EOL: 2018-11-15)
- [CHANGELOG-1.11](docs/CHANGELOG-1.11.md) (EOL: 2018-09-19)

703
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
description = "Parity Ethereum client"
name = "parity-ethereum"
# NOTE Make sure to update util/version/Cargo.toml as well
version = "2.4.3"
version = "2.5.2"
license = "GPL-3.0"
authors = ["Parity Technologies <admin@parity.io>"]
@@ -118,10 +118,13 @@ path = "parity/lib.rs"
path = "parity/main.rs"
name = "parity"
[profile.dev]
[profile.test]
lto = false
opt-level = 3 # makes tests slower to compile, but faster to run
[profile.release]
debug = false
lto = true
[workspace]
# This should only list projects that are not

View File

@@ -7,6 +7,7 @@ name = "cli-signer"
version = "1.4.0"
[dependencies]
ethereum-types = "0.4"
futures = "0.1"
rpassword = "1.0"
parity-rpc = { path = "../rpc" }

View File

@@ -7,6 +7,7 @@ name = "parity-rpc-client"
version = "1.4.0"
[dependencies]
ethereum-types = "0.4"
futures = "0.1"
log = "0.4"
serde = "1.0"

View File

@@ -17,6 +17,7 @@
pub mod client;
pub mod signer_client;
extern crate ethereum_types;
extern crate futures;
extern crate jsonrpc_core;
extern crate jsonrpc_ws_server as ws;

View File

@@ -15,7 +15,8 @@
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use client::{Rpc, RpcError};
use rpc::signer::{ConfirmationRequest, TransactionModification, U256, TransactionCondition};
use ethereum_types::U256;
use rpc::signer::{ConfirmationRequest, TransactionModification, TransactionCondition};
use serde;
use serde_json::{Value as JsonValue, to_value};
use std::path::PathBuf;

View File

@@ -14,13 +14,15 @@
// You should have received a copy of the GNU General Public License
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
extern crate ethereum_types;
extern crate futures;
extern crate rpassword;
extern crate parity_rpc as rpc;
extern crate parity_rpc_client as client;
use rpc::signer::{U256, ConfirmationRequest};
use ethereum_types::U256;
use rpc::signer::ConfirmationRequest;
use client::signer_client::SignerRpc;
use std::io::{Write, BufRead, BufReader, stdout, stdin};
use std::path::PathBuf;

View File

@@ -1,3 +1,78 @@
Note: Parity Ethereum 2.2 reached End-of-Life on 2019-02-25 (EOL).
## Parity-Ethereum [v2.2.11](https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.11) (2019-02-21)
Parity-Ethereum 2.2.11-stable is a maintenance release that fixes snap and docker installations.
The full list of included changes:
- Stable: snap: release untagged versions from branches to the candidate ([#10357](https://github.com/paritytech/parity-ethereum/pull/10357)) ([#10372](https://github.com/paritytech/parity-ethereum/pull/10372))
- Snap: release untagged versions from branches to the candidate snap channel ([#10357](https://github.com/paritytech/parity-ethereum/pull/10357))
- Snap: add the removable-media plug ([#10377](https://github.com/paritytech/parity-ethereum/pull/10377))
- Exchanged old(azure) bootnodes with new(ovh) ones ([#10309](https://github.com/paritytech/parity-ethereum/pull/10309))
- Stable Backports ([#10353](https://github.com/paritytech/parity-ethereum/pull/10353))
- Version: bump stable to 2.2.11
- Snap: prefix version and populate candidate channel ([#10343](https://github.com/paritytech/parity-ethereum/pull/10343))
- Snap: populate candidate releases with beta snaps to avoid stale channel
- Snap: prefix version with v*
- No volumes are needed, just run -v volume:/path/in/the/container ([#10345](https://github.com/paritytech/parity-ethereum/pull/10345))
## Parity-Ethereum [v2.2.10](https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.10) (2019-02-13)
Parity-Ethereum 2.2.10-stable is a security-relevant release. A bug in the JSONRPC-deserialization module can cause crashes of all versions of Parity Ethereum nodes if an attacker is able to submit a specially-crafted RPC to certain publicly available endpoints.
- https://www.parity.io/new-parity-ethereum-update-fixes-several-rpc-vulnerabilities/
The full list of included changes:
- Additional error for invalid gas ([#10327](https://github.com/paritytech/parity-ethereum/pull/10327)) ([#10329](https://github.com/paritytech/parity-ethereum/pull/10329))
- Backports for Stable 2.2.10 ([#10332](https://github.com/paritytech/parity-ethereum/pull/10332))
- fix(docker-aarch64) : cross-compile config ([#9798](https://github.com/paritytech/parity-ethereum/pull/9798))
- import rpc transactions sequentially ([#10051](https://github.com/paritytech/parity-ethereum/pull/10051))
- fix(docker): fix not receives SIGINT ([#10059](https://github.com/paritytech/parity-ethereum/pull/10059))
- snap: official image / test ([#10168](https://github.com/paritytech/parity-ethereum/pull/10168))
- perform stripping during build ([#10208](https://github.com/paritytech/parity-ethereum/pull/10208))
- Additional tests for uint/hash/bytes deserialization. ([#10279](https://github.com/paritytech/parity-ethereum/pull/10279))
- Don't run the CPP example on CI ([#10285](https://github.com/paritytech/parity-ethereum/pull/10285))
- CI optimizations ([#10297](https://github.com/paritytech/parity-ethereum/pull/10297))
- fix publish job ([#10317](https://github.com/paritytech/parity-ethereum/pull/10317))
- Add Statetest support for Constantinople Fix ([#10323](https://github.com/paritytech/parity-ethereum/pull/10323))
- Add helper for Timestamp overflows ([#10330](https://github.com/paritytech/parity-ethereum/pull/10330))
- Don't add discovery initiators to the node table ([#10305](https://github.com/paritytech/parity-ethereum/pull/10305))
- change docker image based on debian instead of ubuntu due to the chan ([#10336](https://github.com/paritytech/parity-ethereum/pull/10336))
- role back docker build image and docker deploy image to ubuntu:xenial based ([#10338](https://github.com/paritytech/parity-ethereum/pull/10338))
## Parity-Ethereum [v2.2.9](https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.9) (2019-02-03)
Parity-Ethereum 2.2.9-stable is a security-relevant release. A bug in the JSONRPC-deserialization module can cause crashes of all versions of Parity Ethereum nodes if an attacker is able to submit a specially-crafted RPC to certain publicly available endpoints.
- https://www.parity.io/security-alert-parity-ethereum-03-02/
The full list of included changes:
- Additional tests for uint deserialization. ([#10279](https://github.com/paritytech/parity-ethereum/pull/10279)) ([#10281](https://github.com/paritytech/parity-ethereum/pull/10281))
- Version: bump stable to 2.2.9 ([#10282](https://github.com/paritytech/parity-ethereum/pull/10282))
## Parity-Ethereum [v2.2.8](https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.8) (2019-02-01)
Parity-Ethereum 2.2.8-stable is a consensus-relevant release that enables _St. Petersfork_ on:
- Ethereum Block `7280000` (along with Constantinople)
- Kovan Block `10255201`
- Ropsten Block `4939394`
- POA Sokol Block `7026400`
In addition to this, Constantinople is cancelled for the POA Core network. Upgrading is mandatory for clients on any of these chains.
The full list of included changes:
- Backports for stable 2.2.8 ([#10224](https://github.com/paritytech/parity-ethereum/pull/10224))
- Update for Android cross-compilation. ([#10180](https://github.com/paritytech/parity-ethereum/pull/10180))
- Cancel Constantinople HF on POA Core ([#10198](https://github.com/paritytech/parity-ethereum/pull/10198))
- Add EIP-1283 disable transition ([#10214](https://github.com/paritytech/parity-ethereum/pull/10214))
- Enable St-Peters-Fork ("Constantinople Fix") ([#10223](https://github.com/paritytech/parity-ethereum/pull/10223))
- Stable: Macos heapsize force jemalloc ([#10234](https://github.com/paritytech/parity-ethereum/pull/10234)) ([#10258](https://github.com/paritytech/parity-ethereum/pull/10258))
## Parity-Ethereum [v2.2.7](https://github.com/paritytech/parity-ethereum/releases/tag/v2.2.7) (2019-01-15)
Parity-Ethereum 2.2.7-stable is a consensus-relevant security release that reverts Constantinople on the Ethereum network. Upgrading is mandatory for Ethereum, and strongly recommended for other networks.

288
docs/CHANGELOG-2.3.md Normal file
View File

@@ -0,0 +1,288 @@
## Parity-Ethereum [v2.3.8](https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.8) (2019-03-22)
Parity-Ethereum 2.3.8-stable is a bugfix release that improves performance and stability. This patch release contains a critical bug fix where serving light clients previously led to client crashes. Upgrading is highly recommended.
The full list of included changes:
- 2.3.8 stable backports ([#10507](https://github.com/paritytech/parity-ethereum/pull/10507))
- Version: bump stable
- Add additional request tests ([#10503](https://github.com/paritytech/parity-ethereum/pull/10503))
## Parity-Ethereum [v2.3.7](https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.7) (2019-03-20)
Parity-Ethereum 2.3.7-stable is a bugfix release that improves performance and stability.
The full list of included changes:
- 2.3.7 stable backports ([#10487](https://github.com/paritytech/parity-ethereum/pull/10487))
- Version: bump stable
- Сaching through docker volume ([#10477](https://github.com/paritytech/parity-ethereum/pull/10477))
- fix win&mac build ([#10486](https://github.com/paritytech/parity-ethereum/pull/10486))
- fix(extract `timestamp_checked_add` as lib) ([#10383](https://github.com/paritytech/parity-ethereum/pull/10383))
## Parity-Ethereum [v2.3.6](https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.6) (2019-03-19)
Parity-Ethereum 2.3.6-stable is a bugfix release that improves performance and stability.
The full list of included changes:
- 2.3.6 stable backports ([#10470](https://github.com/paritytech/parity-ethereum/pull/10470))
- Version: bump stable
- CI publish to aws ([#10446](https://github.com/paritytech/parity-ethereum/pull/10446))
- Ensure static validator set changes are recognized ([#10467](https://github.com/paritytech/parity-ethereum/pull/10467))
- CI aws git checkout ([#10451](https://github.com/paritytech/parity-ethereum/pull/10451))
- Revert "CI aws git checkout ([#10451](https://github.com/paritytech/parity-ethereum/pull/10451))" ([#10456](https://github.com/paritytech/parity-ethereum/pull/10456))
- Tests parallelized ([#10452](https://github.com/paritytech/parity-ethereum/pull/10452))
## Parity-Ethereum [v2.3.5](https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.5) (2019-02-25)
Parity-Ethereum 2.3.5-stable is a bugfix release that improves performance and stability.
Note, all 2.2 releases and older are now unsupported and upgrading is recommended.
The full list of included changes:
- More Backports for Stable 2.3.5 ([#10430](https://github.com/paritytech/parity-ethereum/pull/10430))
- Revert some changes, could be buggy ([#10399](https://github.com/paritytech/parity-ethereum/pull/10399))
- Ci: clean up gitlab-ci.yml leftovers from previous merge ([#10429](https://github.com/paritytech/parity-ethereum/pull/10429))
- 10000 > 5000 ([#10422](https://github.com/paritytech/parity-ethereum/pull/10422))
- Fix underflow in pip, closes [#10419](https://github.com/paritytech/parity-ethereum/pull/10419) ([#10423](https://github.com/paritytech/parity-ethereum/pull/10423))
- Fix panic when logging directory does not exist, closes [#10420](https://github.com/paritytech/parity-ethereum/pull/10420) ([#10424](https://github.com/paritytech/parity-ethereum/pull/10424))
- Update hardcoded headers for Foundation, Ropsten, Kovan and Classic ([#10417](https://github.com/paritytech/parity-ethereum/pull/10417))
- Backports for Stable 2.3.5 ([#10414](https://github.com/paritytech/parity-ethereum/pull/10414))
- No-git for publish jobs, empty artifacts dir ([#10393](https://github.com/paritytech/parity-ethereum/pull/10393))
- Snap: reenable i386, arm64, armhf architecture publishing ([#10386](https://github.com/paritytech/parity-ethereum/pull/10386))
- Tx pool: always accept local transactions ([#10375](https://github.com/paritytech/parity-ethereum/pull/10375))
- Fix to_pod storage trie value decoding ([#10368)](https://github.com/paritytech/parity-ethereum/pull/10368))
- Version: mark 2.3.5 as stable
## Parity-Ethereum [v2.3.4](https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.4) (2019-02-21)
Parity-Ethereum 2.3.4-beta is a maintenance release that fixes snap and docker installations.
The full list of included changes:
- Beta: snap: release untagged versions from branches to the candidate ([#10357](https://github.com/paritytech/parity-ethereum/pull/10357)) ([#10373](https://github.com/paritytech/parity-ethereum/pull/10373))
- Snap: release untagged versions from branches to the candidate snap channel ([#10357](https://github.com/paritytech/parity-ethereum/pull/10357))
- Snap: add the removable-media plug ([#10377](https://github.com/paritytech/parity-ethereum/pull/10377))
- Exchanged old(azure) bootnodes with new(ovh) ones ([#10309](https://github.com/paritytech/parity-ethereum/pull/10309))
- Beta Backports ([#10354](https://github.com/paritytech/parity-ethereum/pull/10354))
- Version: bump beta to 2.3.4
- Snap: prefix version and populate candidate channel ([#10343](https://github.com/paritytech/parity-ethereum/pull/10343))
- Snap: populate candidate releases with beta snaps to avoid stale channel
- Snap: prefix version with v*
- No volumes are needed, just run -v volume:/path/in/the/container ([#10345](https://github.com/paritytech/parity-ethereum/pull/10345))
## Parity-Ethereum [v2.3.3](https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.3) (2019-02-13)
Parity-Ethereum 2.3.3-beta is a security-relevant release. A bug in the JSONRPC-deserialization module can cause crashes of all versions of Parity Ethereum nodes if an attacker is able to submit a specially-crafted RPC to certain publicly available endpoints.
- https://www.parity.io/new-parity-ethereum-update-fixes-several-rpc-vulnerabilities/
The full list of included changes:
- Additional error for invalid gas ([#10327](https://github.com/paritytech/parity-ethereum/pull/10327)) ([#10328](https://github.com/paritytech/parity-ethereum/pull/10328))
- Backports for Beta 2.3.3 ([#10333](https://github.com/paritytech/parity-ethereum/pull/10333))
- Properly handle check_epoch_end_signal errors ([#10015](https://github.com/paritytech/parity-ethereum/pull/10015))
- import rpc transactions sequentially ([#10051](https://github.com/paritytech/parity-ethereum/pull/10051))
- fix(docker): fix not receives SIGINT ([#10059](https://github.com/paritytech/parity-ethereum/pull/10059))
- snap: official image / test ([#10168](https://github.com/paritytech/parity-ethereum/pull/10168))
- Extract CallContract and RegistryInfo traits into their own crate ([#10178](https://github.com/paritytech/parity-ethereum/pull/10178))
- perform stripping during build ([#10208](https://github.com/paritytech/parity-ethereum/pull/10208))
- Remove CallContract and RegistryInfo re-exports from `ethcore/client` ([#10205](https://github.com/paritytech/parity-ethereum/pull/10205))
- fixed: types::transaction::SignedTransaction; ([#10229](https://github.com/paritytech/parity-ethereum/pull/10229))
- Additional tests for uint/hash/bytes deserialization. ([#10279](https://github.com/paritytech/parity-ethereum/pull/10279))
- Fix Windows build ([#10284](https://github.com/paritytech/parity-ethereum/pull/10284))
- Don't run the CPP example on CI ([#10285](https://github.com/paritytech/parity-ethereum/pull/10285))
- CI optimizations ([#10297](https://github.com/paritytech/parity-ethereum/pull/10297))
- fix publish job ([#10317](https://github.com/paritytech/parity-ethereum/pull/10317))
- Add Statetest support for Constantinople Fix ([#10323](https://github.com/paritytech/parity-ethereum/pull/10323))
- Add helper for Timestamp overflows ([#10330](https://github.com/paritytech/parity-ethereum/pull/10330))
- Don't add discovery initiators to the node table ([#10305](https://github.com/paritytech/parity-ethereum/pull/10305))
- change docker image based on debian instead of ubuntu due to the chan ([#10336](https://github.com/paritytech/parity-ethereum/pull/10336))
- role back docker build image and docker deploy image to ubuntu:xenial based ([#10338](https://github.com/paritytech/parity-ethereum/pull/10338))
## Parity-Ethereum [v2.3.2](https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.2) (2019-02-03)
Parity-Ethereum 2.3.2-stable is a security-relevant release. A bug in the JSONRPC-deserialization module can cause crashes of all versions of Parity Ethereum nodes if an attacker is able to submit a specially-crafted RPC to certain publicly available endpoints.
- https://www.parity.io/security-alert-parity-ethereum-03-02/
The full list of included changes:
- Version: bump beta to 2.3.2 ([#10283](https://github.com/paritytech/parity-ethereum/pull/10283))
- Additional tests for uint deserialization. ([#10279](https://github.com/paritytech/parity-ethereum/pull/10279)) ([#10280](https://github.com/paritytech/parity-ethereum/pull/10280))
- Backport [#10285](https://github.com/paritytech/parity-ethereum/pull/10285) to beta ([#10286](https://github.com/paritytech/parity-ethereum/pull/10286))
## Parity-Ethereum [v2.3.1](https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.1) (2019-02-01)
Parity-Ethereum 2.3.1-beta is a consensus-relevant release that enables _St. Petersfork_ on:
- Ethereum Block `7280000` (along with Constantinople)
- Kovan Block `10255201`
- Ropsten Block `4939394`
- POA Sokol Block `7026400`
In addition to this, Constantinople is cancelled for the POA Core network. Upgrading is mandatory for clients on any of these chains.
The full list of included changes:
- Backports for beta 2.3.1 ([#10225](https://github.com/paritytech/parity-ethereum/pull/10225))
- Fix _cannot recursively call into `Core`_ issue ([#10144](https://github.com/paritytech/parity-ethereum/pull/10144))
- Update for Android cross-compilation. ([#10180](https://github.com/paritytech/parity-ethereum/pull/10180))
- Fix _cannot recursively call into `Core`_ - Part 2 ([#10195](https://github.com/paritytech/parity-ethereum/pull/10195))
- Cancel Constantinople HF on POA Core ([#10198](https://github.com/paritytech/parity-ethereum/pull/10198))
- Add EIP-1283 disable transition ([#10214](https://github.com/paritytech/parity-ethereum/pull/10214))
- Enable St-Peters-Fork ("Constantinople Fix") ([#10223](https://github.com/paritytech/parity-ethereum/pull/10223))
- Beta: Macos heapsize force jemalloc ([#10234](https://github.com/paritytech/parity-ethereum/pull/10234)) ([#10259](https://github.com/paritytech/parity-ethereum/pull/10259))
## Parity-Ethereum [v2.3.0](https://github.com/paritytech/parity-ethereum/releases/tag/v2.3.0) (2019-01-16)
Parity-Ethereum 2.3.0-beta is a consensus-relevant security release that reverts Constantinople on the Ethereum network. Upgrading is mandatory for Ethereum, and strongly recommended for other networks.
- **Consensus** - Ethereum Network: Pull Constantinople protocol upgrade on Ethereum ([#10189](https://github.com/paritytech/parity-ethereum/pull/10189))
- Read more: [Security Alert: Ethereum Constantinople Postponement](https://blog.ethereum.org/2019/01/15/security-alert-ethereum-constantinople-postponement/)
- **Networking** - All networks: Ping nodes from discovery ([#10167](https://github.com/paritytech/parity-ethereum/pull/10167))
- **Wasm** - Kovan Network: Update pwasm-utils to 0.6.1 ([#10134](https://github.com/paritytech/parity-ethereum/pull/10134))
Other notable changes:
- Existing blocks in the database are now kept when restoring a Snapshot. ([#8643](https://github.com/paritytech/parity-ethereum/pull/8643))
- Block and transaction propagation is improved significantly. ([#9954](https://github.com/paritytech/parity-ethereum/pull/9954))
- The ERC-191 Signed Data Standard is now supported by `personal_sign191`. ([#9701](https://github.com/paritytech/parity-ethereum/pull/9701))
- Add support for ERC-191/712 `eth_signTypedData` as a standard for machine-verifiable and human-readable typed data signing with Ethereum keys. ([#9631](https://github.com/paritytech/parity-ethereum/pull/9631))
- Add support for ERC-1186 `eth_getProof` ([#9001](https://github.com/paritytech/parity-ethereum/pull/9001))
- Add experimental RPCs flag to enable ERC-191, ERC-712, and ERC-1186 APIs via `--jsonrpc-experimental` ([#9928](https://github.com/paritytech/parity-ethereum/pull/9928))
- Make `CALLCODE` to trace value to be the code address. ([#9881](https://github.com/paritytech/parity-ethereum/pull/9881))
Configuration changes:
- The EIP-98 transition is now disabled by default. If you previously had no `eip98transition` specified in your chain specification, you would enable this now manually on block `0x0`. ([#9955](https://github.com/paritytech/parity-ethereum/pull/9955))
- Also, unknown fields in chain specs are now rejected. ([#9972](https://github.com/paritytech/parity-ethereum/pull/9972))
- The Tendermint engine was removed from Parity Ethereum and is no longer available and maintained. ([#9980](https://github.com/paritytech/parity-ethereum/pull/9980))
- Ropsten testnet data and keys moved from `test/` to `ropsten/` subdir. To reuse your old keys and data either copy or symlink them to the new location. ([#10123](https://github.com/paritytech/parity-ethereum/pull/10123))
- Strict empty steps validation ([#10041](https://github.com/paritytech/parity-ethereum/pull/10041))
- If you have a chain with`empty_steps` already running, some blocks most likely contain non-strict entries (unordered or duplicated empty steps). In this release `strict_empty_steps_transition` is enabled by default at block `0x0` for any chain with `empty_steps`.
- If your network uses `empty_steps` you **must** (A) plan a hard fork and change `strict_empty_steps_transition` to the desired fork block and (B) update the clients of the whole network to 2.2.7-stable / 2.3.0-beta. If for some reason you don't want to do this please set`strict_empty_steps_transition` to `0xfffffffff` to disable it.
_Note:_ This release marks Parity 2.3 as _beta_. All versions of Parity 2.2 are now considered _stable_.
The full list of included changes:
- Backports for 2.3.0 beta ([#10164](https://github.com/paritytech/parity-ethereum/pull/10164))
- Snap: fix path in script ([#10157](https://github.com/paritytech/parity-ethereum/pull/10157))
- Make sure parent block is not in importing queue when importing ancient blocks ([#10138](https://github.com/paritytech/parity-ethereum/pull/10138))
- Ci: re-enable snap publishing ([#10142](https://github.com/paritytech/parity-ethereum/pull/10142))
- Hf in POA Core (2019-01-18) - Constantinople ([#10155](https://github.com/paritytech/parity-ethereum/pull/10155))
- Update EWF's tobalaba chainspec ([#10152](https://github.com/paritytech/parity-ethereum/pull/10152))
- Replace ethcore-logger with env-logger. ([#10102](https://github.com/paritytech/parity-ethereum/pull/10102))
- Finality: dont require chain head to be in the chain ([#10054](https://github.com/paritytech/parity-ethereum/pull/10054))
- Remove caching for node connections ([#10143](https://github.com/paritytech/parity-ethereum/pull/10143))
- Blooms file iterator empty on out of range position. ([#10145](https://github.com/paritytech/parity-ethereum/pull/10145))
- Autogen docs for the "Configuring Parity Ethereum" wiki page. ([#10067](https://github.com/paritytech/parity-ethereum/pull/10067))
- Misc: bump license header to 2019 ([#10135](https://github.com/paritytech/parity-ethereum/pull/10135))
- Hide most of the logs from cpp example. ([#10139](https://github.com/paritytech/parity-ethereum/pull/10139))
- Don't try to send oversized packets ([#10042](https://github.com/paritytech/parity-ethereum/pull/10042))
- Private tx enabled flag added into STATUS packet ([#9999](https://github.com/paritytech/parity-ethereum/pull/9999))
- Update pwasm-utils to 0.6.1 ([#10134](https://github.com/paritytech/parity-ethereum/pull/10134))
- Extract blockchain from ethcore ([#10114](https://github.com/paritytech/parity-ethereum/pull/10114))
- Ethcore: update hardcoded headers ([#10123](https://github.com/paritytech/parity-ethereum/pull/10123))
- Identity fix ([#10128](https://github.com/paritytech/parity-ethereum/pull/10128))
- Use LenCachingMutex to optimize verification. ([#10117](https://github.com/paritytech/parity-ethereum/pull/10117))
- Pyethereum keystore support ([#9710](https://github.com/paritytech/parity-ethereum/pull/9710))
- Bump rocksdb-sys to 0.5.5 ([#10124](https://github.com/paritytech/parity-ethereum/pull/10124))
- Parity-clib: `async C bindings to RPC requests` + `subscribe/unsubscribe to websocket events` ([#9920](https://github.com/paritytech/parity-ethereum/pull/9920))
- Refactor (hardware wallet) : reduce the number of threads ([#9644](https://github.com/paritytech/parity-ethereum/pull/9644))
- Hf in POA Sokol (2019-01-04) ([#10077](https://github.com/paritytech/parity-ethereum/pull/10077))
- Fix broken links ([#10119](https://github.com/paritytech/parity-ethereum/pull/10119))
- Follow-up to [#10105](https://github.com/paritytech/parity-ethereum/issues/10105) ([#10107](https://github.com/paritytech/parity-ethereum/pull/10107))
- Move EIP-712 crate back to parity-ethereum ([#10106](https://github.com/paritytech/parity-ethereum/pull/10106))
- Move a bunch of stuff around ([#10101](https://github.com/paritytech/parity-ethereum/pull/10101))
- Revert "Add --frozen when running cargo ([#10081](https://github.com/paritytech/parity-ethereum/pull/10081))" ([#10105](https://github.com/paritytech/parity-ethereum/pull/10105))
- Fix left over small grumbles on whitespaces ([#10084](https://github.com/paritytech/parity-ethereum/pull/10084))
- Add --frozen when running cargo ([#10081](https://github.com/paritytech/parity-ethereum/pull/10081))
- Fix pubsub new_blocks notifications to include all blocks ([#9987](https://github.com/paritytech/parity-ethereum/pull/9987))
- Update some dependencies for compilation with pc-windows-gnu ([#10082](https://github.com/paritytech/parity-ethereum/pull/10082))
- Fill transaction hash on ethGetLog of light client. ([#9938](https://github.com/paritytech/parity-ethereum/pull/9938))
- Update changelog update for 2.2.5-beta and 2.1.10-stable ([#10064](https://github.com/paritytech/parity-ethereum/pull/10064))
- Implement len caching for parking_lot RwLock ([#10032](https://github.com/paritytech/parity-ethereum/pull/10032))
- Update parking_lot to 0.7 ([#10050](https://github.com/paritytech/parity-ethereum/pull/10050))
- Bump crossbeam. ([#10048](https://github.com/paritytech/parity-ethereum/pull/10048))
- Ethcore: enable constantinople on ethereum ([#10031](https://github.com/paritytech/parity-ethereum/pull/10031))
- Strict empty steps validation ([#10041](https://github.com/paritytech/parity-ethereum/pull/10041))
- Center the Subtitle, use some CAPS ([#10034](https://github.com/paritytech/parity-ethereum/pull/10034))
- Change test miner max memory to malloc reports. ([#10024](https://github.com/paritytech/parity-ethereum/pull/10024))
- Sort the storage for private state ([#10018](https://github.com/paritytech/parity-ethereum/pull/10018))
- Fix: test corpus_inaccessible panic ([#10019](https://github.com/paritytech/parity-ethereum/pull/10019))
- Ci: move future releases to ethereum subdir on s3 ([#10017](https://github.com/paritytech/parity-ethereum/pull/10017))
- Light(on_demand): decrease default time window to 10 secs ([#10016](https://github.com/paritytech/parity-ethereum/pull/10016))
- Light client : failsafe crate (circuit breaker) ([#9790](https://github.com/paritytech/parity-ethereum/pull/9790))
- Lencachingmutex ([#9988](https://github.com/paritytech/parity-ethereum/pull/9988))
- Version and notification for private contract wrapper added ([#9761](https://github.com/paritytech/parity-ethereum/pull/9761))
- Handle failing case for update account cache in require ([#9989](https://github.com/paritytech/parity-ethereum/pull/9989))
- Add tokio runtime to ethcore io worker ([#9979](https://github.com/paritytech/parity-ethereum/pull/9979))
- Move daemonize before creating account provider ([#10003](https://github.com/paritytech/parity-ethereum/pull/10003))
- Docs: update changelogs ([#9990](https://github.com/paritytech/parity-ethereum/pull/9990))
- Fix daemonize ([#10000](https://github.com/paritytech/parity-ethereum/pull/10000))
- Fix Bloom migration ([#9992](https://github.com/paritytech/parity-ethereum/pull/9992))
- Remove tendermint engine support ([#9980](https://github.com/paritytech/parity-ethereum/pull/9980))
- Calculate gas for deployment transaction ([#9840](https://github.com/paritytech/parity-ethereum/pull/9840))
- Fix unstable peers and slowness in sync ([#9967](https://github.com/paritytech/parity-ethereum/pull/9967))
- Adds parity_verifySignature RPC method ([#9507](https://github.com/paritytech/parity-ethereum/pull/9507))
- Improve block and transaction propagation ([#9954](https://github.com/paritytech/parity-ethereum/pull/9954))
- Deny unknown fields for chainspec ([#9972](https://github.com/paritytech/parity-ethereum/pull/9972))
- Fix docker build ([#9971](https://github.com/paritytech/parity-ethereum/pull/9971))
- Ci: rearrange pipeline by logic ([#9970](https://github.com/paritytech/parity-ethereum/pull/9970))
- Add changelogs for 2.0.9, 2.1.4, 2.1.6, and 2.2.1 ([#9963](https://github.com/paritytech/parity-ethereum/pull/9963))
- Add Error message when sync is still in progress. ([#9475](https://github.com/paritytech/parity-ethereum/pull/9475))
- Make CALLCODE to trace value to be the code address ([#9881](https://github.com/paritytech/parity-ethereum/pull/9881))
- Fix light client informant while syncing ([#9932](https://github.com/paritytech/parity-ethereum/pull/9932))
- Add a optional json dump state to evm-bin ([#9706](https://github.com/paritytech/parity-ethereum/pull/9706))
- Disable EIP-98 transition by default ([#9955](https://github.com/paritytech/parity-ethereum/pull/9955))
- Remove secret_store runtimes. ([#9888](https://github.com/paritytech/parity-ethereum/pull/9888))
- Fix a deadlock ([#9952](https://github.com/paritytech/parity-ethereum/pull/9952))
- Chore(eip712): remove unused `failure-derive` ([#9958](https://github.com/paritytech/parity-ethereum/pull/9958))
- Do not use the home directory as the working dir in docker ([#9834](https://github.com/paritytech/parity-ethereum/pull/9834))
- Prevent silent errors in daemon mode, closes [#9367](https://github.com/paritytech/parity-ethereum/issues/9367) ([#9946](https://github.com/paritytech/parity-ethereum/pull/9946))
- Fix empty steps ([#9939](https://github.com/paritytech/parity-ethereum/pull/9939))
- Adjust requests costs for light client ([#9925](https://github.com/paritytech/parity-ethereum/pull/9925))
- Eip-1186: add `eth_getProof` RPC-Method ([#9001](https://github.com/paritytech/parity-ethereum/pull/9001))
- Missing blocks in filter_changes RPC ([#9947](https://github.com/paritytech/parity-ethereum/pull/9947))
- Allow rust-nightly builds fail in nightly builds ([#9944](https://github.com/paritytech/parity-ethereum/pull/9944))
- Update eth-secp256k1 to include fix for BSDs ([#9935](https://github.com/paritytech/parity-ethereum/pull/9935))
- Unbreak build on rust -stable ([#9934](https://github.com/paritytech/parity-ethereum/pull/9934))
- Keep existing blocks when restoring a Snapshot ([#8643](https://github.com/paritytech/parity-ethereum/pull/8643))
- Add experimental RPCs flag ([#9928](https://github.com/paritytech/parity-ethereum/pull/9928))
- Clarify poll lifetime ([#9922](https://github.com/paritytech/parity-ethereum/pull/9922))
- Docs(require rust 1.30) ([#9923](https://github.com/paritytech/parity-ethereum/pull/9923))
- Use block header for building finality ([#9914](https://github.com/paritytech/parity-ethereum/pull/9914))
- Simplify cargo audit ([#9918](https://github.com/paritytech/parity-ethereum/pull/9918))
- Light-fetch: Differentiate between out-of-gas/manual throw and use required gas from response on failure ([#9824](https://github.com/paritytech/parity-ethereum/pull/9824))
- Eip 191 ([#9701](https://github.com/paritytech/parity-ethereum/pull/9701))
- Fix(logger): `reqwest` no longer a dependency ([#9908](https://github.com/paritytech/parity-ethereum/pull/9908))
- Remove rust-toolchain file ([#9906](https://github.com/paritytech/parity-ethereum/pull/9906))
- Foundation: 6692865, ropsten: 4417537, kovan: 9363457 ([#9907](https://github.com/paritytech/parity-ethereum/pull/9907))
- Ethcore: use Machine::verify_transaction on parent block ([#9900](https://github.com/paritytech/parity-ethereum/pull/9900))
- Chore(rpc-tests): remove unused rand ([#9896](https://github.com/paritytech/parity-ethereum/pull/9896))
- Fix: Intermittent failing CI due to addr in use ([#9885](https://github.com/paritytech/parity-ethereum/pull/9885))
- Chore(bump docopt): 0.8 -> 1.0 ([#9889](https://github.com/paritytech/parity-ethereum/pull/9889))
- Use expect ([#9883](https://github.com/paritytech/parity-ethereum/pull/9883))
- Use Weak reference in PubSubClient ([#9886](https://github.com/paritytech/parity-ethereum/pull/9886))
- Ci: nuke the gitlab caches ([#9855](https://github.com/paritytech/parity-ethereum/pull/9855))
- Remove unused code ([#9884](https://github.com/paritytech/parity-ethereum/pull/9884))
- Fix json tracer overflow ([#9873](https://github.com/paritytech/parity-ethereum/pull/9873))
- Allow to seal work on latest block ([#9876](https://github.com/paritytech/parity-ethereum/pull/9876))
- Fix docker script ([#9854](https://github.com/paritytech/parity-ethereum/pull/9854))
- Health endpoint ([#9847](https://github.com/paritytech/parity-ethereum/pull/9847))
- Gitlab-ci: make android release build succeed ([#9743](https://github.com/paritytech/parity-ethereum/pull/9743))
- Clean up existing benchmarks ([#9839](https://github.com/paritytech/parity-ethereum/pull/9839))
- Update Callisto block reward code to support HF1 ([#9811](https://github.com/paritytech/parity-ethereum/pull/9811))
- Option to disable keep alive for JSON-RPC http transport ([#9848](https://github.com/paritytech/parity-ethereum/pull/9848))
- Classic.json Bootnode Update ([#9828](https://github.com/paritytech/parity-ethereum/pull/9828))
- Support MIX. ([#9767](https://github.com/paritytech/parity-ethereum/pull/9767))
- Ci: remove failing tests for android, windows, and macos ([#9788](https://github.com/paritytech/parity-ethereum/pull/9788))
- Implement NoProof for json tests and update tests reference (replaces [#9744](https://github.com/paritytech/parity-ethereum/issues/9744)) ([#9814](https://github.com/paritytech/parity-ethereum/pull/9814))
- Chore(bump regex) ([#9842](https://github.com/paritytech/parity-ethereum/pull/9842))
- Ignore global cache for patched accounts ([#9752](https://github.com/paritytech/parity-ethereum/pull/9752))
- Move state root verification before gas used ([#9841](https://github.com/paritytech/parity-ethereum/pull/9841))
- Fix(docker-aarch64) : cross-compile config ([#9798](https://github.com/paritytech/parity-ethereum/pull/9798))
- Version: bump nightly to 2.3.0 ([#9819](https://github.com/paritytech/parity-ethereum/pull/9819))
- Tests modification for windows CI ([#9671](https://github.com/paritytech/parity-ethereum/pull/9671))
- Eip-712 implementation ([#9631](https://github.com/paritytech/parity-ethereum/pull/9631))
- Fix typo ([#9826](https://github.com/paritytech/parity-ethereum/pull/9826))
- Clean up serde rename and use rename_all = camelCase when possible ([#9823](https://github.com/paritytech/parity-ethereum/pull/9823))

View File

@@ -39,7 +39,7 @@ keccak-hasher = { path = "../util/keccak-hasher" }
kvdb = "0.1"
kvdb-memorydb = "0.1"
kvdb-rocksdb = { version = "0.1.3", optional = true }
lazy_static = "1.0"
lazy_static = "1.2.0"
len-caching-lock = { path = "../util/len-caching-lock" }
log = "0.4"
lru-cache = "0.1"
@@ -50,7 +50,6 @@ num = { version = "0.1", default-features = false, features = ["bigint"] }
num_cpus = "1.2"
parity-bytes = "0.1"
parity-crypto = "0.3.0"
parity-machine = { path = "../machine" }
parity-snappy = "0.1"
parking_lot = "0.7"
trie-db = "0.11.0"

View File

@@ -668,21 +668,6 @@ impl BlockChain {
self.db.key_value().read_with_cache(db::COL_EXTRA, &self.block_details, parent).map_or(false, |d| d.children.contains(hash))
}
/// fetches the list of blocks from best block to n, and n's parent hash
/// where n > 0
pub fn block_headers_from_best_block(&self, n: u32) -> Option<(Vec<encoded::Header>, H256)> {
let mut blocks = Vec::with_capacity(n as usize);
let mut hash = self.best_block_hash();
for _ in 0..n {
let current_hash = self.block_header_data(&hash)?;
hash = current_hash.parent_hash();
blocks.push(current_hash);
}
Some((blocks, hash))
}
/// Returns a tree route between `from` and `to`, which is a tuple of:
///
/// - a vector of hashes of all blocks, ordered from `from` to `to`.
@@ -869,6 +854,14 @@ impl BlockChain {
}
}
/// clears all caches for testing purposes
pub fn clear_cache(&self) {
self.block_bodies.write().clear();
self.block_details.write().clear();
self.block_hashes.write().clear();
self.block_headers.write().clear();
}
/// Update the best ancient block to the given hash, after checking that
/// it's directly linked to the currently known best ancient block
pub fn update_best_ancient_block(&self, hash: &H256) {

View File

@@ -14,6 +14,7 @@ vm = { path = "../vm" }
keccak-hash = "0.1"
parking_lot = "0.7"
memory-cache = { path = "../../util/memory-cache" }
num-bigint = "0.2"
[dev-dependencies]
rustc-hex = "1.0"

View File

@@ -45,7 +45,9 @@ criterion_group!(
mem_gas_calculation_same_usize,
mem_gas_calculation_same_u256,
mem_gas_calculation_increasing_usize,
mem_gas_calculation_increasing_u256
mem_gas_calculation_increasing_u256,
blockhash_mulmod_small,
blockhash_mulmod_large,
);
criterion_main!(basic);
@@ -150,6 +152,54 @@ fn mem_gas_calculation_increasing(gas: U256, b: &mut Bencher) {
});
}
fn blockhash_mulmod_small(b: &mut Criterion) {
b.bench_function("blockhash_mulmod_small", |b| {
let factory = Factory::default();
let mut ext = FakeExt::new();
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
b.iter(|| {
let code = black_box(
"6080604052348015600f57600080fd5b5060005a90505b60c881111560de5760017effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80095060017effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80095060017effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80095060017effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80095060017effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8009505a90506016565b506035806100ed6000396000f3fe6080604052600080fdfea165627a7a72305820bde4a0ac6d0fac28fc879244baf8a6a0eda514bc95fb7ecbcaaebf2556e2687c0029".from_hex().unwrap()
);
let mut params = ActionParams::default();
params.address = address.clone();
params.gas = U256::from(4_000u64);
params.code = Some(Arc::new(code.clone()));
let vm = factory.create(params, ext.schedule(), 0);
result(vm.exec(&mut ext).ok().unwrap())
});
});
}
fn blockhash_mulmod_large(b: &mut Criterion) {
b.bench_function("blockhash_mulmod_large", |b| {
let factory = Factory::default();
let mut ext = FakeExt::new();
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
b.iter(|| {
let code = black_box(
"608060405234801561001057600080fd5b5060005a90505b60c8811115610177577efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff17efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff08009507efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff17efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff08009507efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff17efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff08009507efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff17efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff08009507efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff17efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff08009505a9050610017565b506035806101866000396000f3fe6080604052600080fdfea165627a7a72305820dcaec306f67bb96f3044fff25c9af2ec66f01d0954d0656964f046f42f2780670029".from_hex().unwrap()
);
let mut params = ActionParams::default();
params.address = address.clone();
params.gas = U256::from(4_000u64);
params.code = Some(Arc::new(code.clone()));
let vm = factory.create(params, ext.schedule(), 0);
result(vm.exec(&mut ext).ok().unwrap())
});
});
}
fn result(r: Result<evm::GasLeft>) -> U256 {
match r {
Ok(GasLeft::Known(gas_left)) => gas_left,

View File

@@ -28,7 +28,8 @@ use std::{cmp, mem};
use std::sync::Arc;
use hash::keccak;
use bytes::Bytes;
use ethereum_types::{U256, U512, H256, Address};
use ethereum_types::{U256, H256, Address};
use num_bigint::BigUint;
use vm::{
self, ActionParams, ParamsType, ActionValue, CallType, MessageCallResult,
@@ -61,6 +62,17 @@ const TWO_POW_96: U256 = U256([0, 0x100000000, 0, 0]); //0x1 00000000 00000000 0
const TWO_POW_224: U256 = U256([0, 0, 0, 0x100000000]); //0x1 00000000 00000000 00000000 00000000 00000000 00000000 00000000
const TWO_POW_248: U256 = U256([0, 0, 0, 0x100000000000000]); //0x1 00000000 00000000 00000000 00000000 00000000 00000000 00000000 000000
fn to_biguint(x: U256) -> BigUint {
let mut bytes = [0u8; 32];
x.to_little_endian(&mut bytes);
BigUint::from_bytes_le(&bytes)
}
fn from_biguint(x: BigUint) -> U256 {
let bytes = x.to_bytes_le();
U256::from_little_endian(&bytes)
}
/// Abstraction over raw vector of Bytes. Easier state management of PC.
struct CodeReader {
position: ProgramCounter,
@@ -1009,11 +1021,12 @@ impl<Cost: CostType> Interpreter<Cost> {
let c = self.stack.pop_back();
self.stack.push(if !c.is_zero() {
// upcast to 512
let a5 = U512::from(a);
let res = a5.overflowing_add(U512::from(b)).0;
let x = res % U512::from(c);
U256::from(x)
let a_num = to_biguint(a);
let b_num = to_biguint(b);
let c_num = to_biguint(c);
let res = a_num + b_num;
let x = res % c_num;
from_biguint(x)
} else {
U256::zero()
});
@@ -1024,10 +1037,12 @@ impl<Cost: CostType> Interpreter<Cost> {
let c = self.stack.pop_back();
self.stack.push(if !c.is_zero() {
let a5 = U512::from(a);
let res = a5.overflowing_mul(U512::from(b)).0;
let x = res % U512::from(c);
U256::from(x)
let a_num = to_biguint(a);
let b_num = to_biguint(b);
let c_num = to_biguint(c);
let res = a_num * b_num;
let x = res % c_num;
from_biguint(x)
} else {
U256::zero()
});

View File

@@ -24,6 +24,7 @@ extern crate vm;
extern crate keccak_hash as hash;
extern crate memory_cache;
extern crate parity_bytes as bytes;
extern crate num_bigint;
#[macro_use]
extern crate lazy_static;

View File

@@ -24,7 +24,6 @@ use std::marker::PhantomData;
use std::sync::Arc;
use std::time::Duration;
use ethcore::executed::{Executed, ExecutionError};
use futures::{Poll, Future, Async};
use futures::sync::oneshot::{self, Receiver};
use network::PeerId;
@@ -41,10 +40,10 @@ use cache::Cache;
use request::{self as basic_request, Request as NetworkRequest};
use self::request::CheckedRequest;
pub use ethcore::executed::ExecutionResult;
pub use self::request::{Request, Response, HeaderRef, Error as ValidityError};
pub use self::request_guard::{RequestGuard, Error as RequestError};
pub use self::response_guard::{ResponseGuard, Error as ResponseGuardError, Inner as ResponseGuardInner};
pub use types::request::ResponseError;
#[cfg(test)]
@@ -54,9 +53,6 @@ pub mod request;
mod request_guard;
mod response_guard;
/// The result of execution
pub type ExecutionResult = Result<Executed, ExecutionError>;
/// The initial backoff interval for OnDemand queries
pub const DEFAULT_REQUEST_MIN_BACKOFF_DURATION: Duration = Duration::from_secs(10);
/// The maximum request interval for OnDemand queries
@@ -70,6 +66,10 @@ pub const DEFAULT_NUM_CONSECUTIVE_FAILED_REQUESTS: usize = 1;
/// OnDemand related errors
pub mod error {
// Silence: `use of deprecated item 'std::error::Error::cause': replaced by Error::source, which can support downcasting`
// https://github.com/paritytech/parity-ethereum/issues/10302
#![allow(deprecated)]
use futures::sync::oneshot::Canceled;
error_chain! {
@@ -94,6 +94,24 @@ pub mod error {
}
}
/// Public interface for performing network requests `OnDemand`
pub trait OnDemandRequester: Send + Sync {
/// Submit a strongly-typed batch of requests.
///
/// Fails if back-reference are not coherent.
fn request<T>(&self, ctx: &BasicContext, requests: T) -> Result<OnResponses<T>, basic_request::NoSuchOutput>
where
T: request::RequestAdapter;
/// Submit a vector of requests to be processed together.
///
/// Fails if back-references are not coherent.
/// The returned vector of responses will correspond to the requests exactly.
fn request_raw(&self, ctx: &BasicContext, requests: Vec<Request>)
-> Result<Receiver<PendingResponse>, basic_request::NoSuchOutput>;
}
// relevant peer info.
#[derive(Debug, Clone, PartialEq, Eq)]
struct Peer {
@@ -355,6 +373,74 @@ pub struct OnDemand {
request_number_of_consecutive_errors: usize
}
impl OnDemandRequester for OnDemand {
fn request_raw(&self, ctx: &BasicContext, requests: Vec<Request>)
-> Result<Receiver<PendingResponse>, basic_request::NoSuchOutput>
{
let (sender, receiver) = oneshot::channel();
if requests.is_empty() {
assert!(sender.send(Ok(Vec::new())).is_ok(), "receiver still in scope; qed");
return Ok(receiver);
}
let mut builder = basic_request::Builder::default();
let responses = Vec::with_capacity(requests.len());
let mut header_producers = HashMap::new();
for (i, request) in requests.into_iter().enumerate() {
let request = CheckedRequest::from(request);
// ensure that all requests needing headers will get them.
if let Some((idx, field)) = request.needs_header() {
// a request chain with a header back-reference is valid only if it both
// points to a request that returns a header and has the same back-reference
// for the block hash.
match header_producers.get(&idx) {
Some(ref f) if &field == *f => {}
_ => return Err(basic_request::NoSuchOutput),
}
}
if let CheckedRequest::HeaderByHash(ref req, _) = request {
header_producers.insert(i, req.0);
}
builder.push(request)?;
}
let requests = builder.build();
let net_requests = requests.clone().map_requests(|req| req.into_net_request());
let capabilities = guess_capabilities(requests.requests());
self.submit_pending(ctx, Pending {
requests,
net_requests,
required_capabilities: capabilities,
responses,
sender,
request_guard: RequestGuard::new(
self.request_number_of_consecutive_errors as u32,
self.request_backoff_rounds_max,
self.request_backoff_start,
self.request_backoff_max,
),
response_guard: ResponseGuard::new(self.response_time_window),
});
Ok(receiver)
}
fn request<T>(&self, ctx: &BasicContext, requests: T) -> Result<OnResponses<T>, basic_request::NoSuchOutput>
where T: request::RequestAdapter
{
self.request_raw(ctx, requests.make_requests()).map(|recv| OnResponses {
receiver: recv,
_marker: PhantomData,
})
}
}
impl OnDemand {
/// Create a new `OnDemand` service with the given cache.
@@ -415,77 +501,6 @@ impl OnDemand {
me
}
/// Submit a vector of requests to be processed together.
///
/// Fails if back-references are not coherent.
/// The returned vector of responses will correspond to the requests exactly.
pub fn request_raw(&self, ctx: &BasicContext, requests: Vec<Request>)
-> Result<Receiver<PendingResponse>, basic_request::NoSuchOutput>
{
let (sender, receiver) = oneshot::channel();
if requests.is_empty() {
assert!(sender.send(Ok(Vec::new())).is_ok(), "receiver still in scope; qed");
return Ok(receiver);
}
let mut builder = basic_request::Builder::default();
let responses = Vec::with_capacity(requests.len());
let mut header_producers = HashMap::new();
for (i, request) in requests.into_iter().enumerate() {
let request = CheckedRequest::from(request);
// ensure that all requests needing headers will get them.
if let Some((idx, field)) = request.needs_header() {
// a request chain with a header back-reference is valid only if it both
// points to a request that returns a header and has the same back-reference
// for the block hash.
match header_producers.get(&idx) {
Some(ref f) if &field == *f => {}
_ => return Err(basic_request::NoSuchOutput),
}
}
if let CheckedRequest::HeaderByHash(ref req, _) = request {
header_producers.insert(i, req.0);
}
builder.push(request)?;
}
let requests = builder.build();
let net_requests = requests.clone().map_requests(|req| req.into_net_request());
let capabilities = guess_capabilities(requests.requests());
self.submit_pending(ctx, Pending {
requests,
net_requests,
required_capabilities: capabilities,
responses,
sender,
request_guard: RequestGuard::new(
self.request_number_of_consecutive_errors as u32,
self.request_backoff_rounds_max,
self.request_backoff_start,
self.request_backoff_max,
),
response_guard: ResponseGuard::new(self.response_time_window),
});
Ok(receiver)
}
/// Submit a strongly-typed batch of requests.
///
/// Fails if back-reference are not coherent.
pub fn request<T>(&self, ctx: &BasicContext, requests: T) -> Result<OnResponses<T>, basic_request::NoSuchOutput>
where T: request::RequestAdapter
{
self.request_raw(ctx, requests.make_requests()).map(|recv| OnResponses {
receiver: recv,
_marker: PhantomData,
})
}
// maybe dispatch pending requests.
// sometimes

View File

@@ -29,7 +29,7 @@ use std::sync::Arc;
use std::time::{Duration, Instant};
use std::thread;
use super::{request, OnDemand, Peer, HeaderRef};
use super::{request, OnDemand, OnDemandRequester, Peer, HeaderRef};
// useful contexts to give the service.
enum Context {

View File

@@ -275,8 +275,7 @@ mod tests {
}
#[test]
#[should_panic]
fn batch_tx_index_backreference_wrong_output() {
fn batch_tx_index_backreference_public_api() {
let mut builder = Builder::default();
builder.push(Request::HeaderProof(IncompleteHeaderProofRequest {
num: 100.into(), // header proof puts hash at output 0.
@@ -286,11 +285,16 @@ mod tests {
})).unwrap();
let mut batch = builder.build();
batch.requests[1].fill(|_req_idx, _out_idx| Ok(Output::Number(42)));
batch.next_complete();
batch.answered += 1;
batch.next_complete();
assert!(batch.next_complete().is_some());
let hdr_proof_res = header_proof::Response {
proof: vec![],
hash: 12.into(),
td: 21.into(),
};
batch.supply_response_unchecked(&hdr_proof_res);
assert!(batch.next_complete().is_some());
}
#[test]
@@ -310,23 +314,4 @@ mod tests {
batch.answered += 1;
assert!(batch.next_complete().is_some());
}
#[test]
#[should_panic]
fn batch_receipts_backreference_wrong_output() {
let mut builder = Builder::default();
builder.push(Request::HeaderProof(IncompleteHeaderProofRequest {
num: 100.into(), // header proof puts hash at output 0.
})).unwrap();
builder.push(Request::Receipts(IncompleteReceiptsRequest {
hash: Field::BackReference(0, 0),
})).unwrap();
let mut batch = builder.build();
batch.requests[1].fill(|_req_idx, _out_idx| Ok(Output::Number(42)));
batch.next_complete();
batch.answered += 1;
batch.next_complete();
}
}

View File

@@ -7,7 +7,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
common-types = { path = "../types" }
error-chain = { version = "0.12", default-features = false }
derive_more = "0.14.0"
ethabi = "6.0"
ethabi-contract = "6.0"
ethabi-derive = "6.0"
@@ -36,7 +36,7 @@ serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
tiny-keccak = "1.4"
transaction-pool = "1.13.2"
transaction-pool = "2.0"
url = "1"
[dev-dependencies]

View File

@@ -31,7 +31,7 @@ use crypto;
use futures::Future;
use fetch::{Fetch, Client as FetchClient, Method, BodyReader, Request};
use bytes::{Bytes, ToPretty};
use error::{Error, ErrorKind};
use error::Error;
use url::Url;
use super::Signer;
use super::key_server_keys::address_to_key;
@@ -111,11 +111,11 @@ impl SecretStoreEncryptor {
return Ok(key);
}
let contract_address_signature = self.sign_contract_address(contract_address)?;
let requester = self.config.key_server_account.ok_or_else(|| ErrorKind::KeyServerAccountNotSet)?;
let requester = self.config.key_server_account.ok_or_else(|| Error::KeyServerAccountNotSet)?;
// key id in SS is H256 && we have H160 here => expand with assitional zeros
let contract_address_extended: H256 = contract_address.into();
let base_url = self.config.base_url.clone().ok_or_else(|| ErrorKind::KeyServerNotSet)?;
let base_url = self.config.base_url.clone().ok_or_else(|| Error::KeyServerNotSet)?;
// prepare request url
let url = format!("{}/{}/{}{}",
@@ -132,16 +132,16 @@ impl SecretStoreEncryptor {
Method::GET
};
let url = Url::from_str(&url).map_err(|e| ErrorKind::Encrypt(e.to_string()))?;
let url = Url::from_str(&url).map_err(|e| Error::Encrypt(e.to_string()))?;
let response = self.client.fetch(Request::new(url, method), Default::default()).wait()
.map_err(|e| ErrorKind::Encrypt(e.to_string()))?;
.map_err(|e| Error::Encrypt(e.to_string()))?;
if response.is_not_found() {
bail!(ErrorKind::EncryptionKeyNotFound(*contract_address));
return Err(Error::EncryptionKeyNotFound(*contract_address));
}
if !response.is_success() {
bail!(ErrorKind::Encrypt(response.status().canonical_reason().unwrap_or("unknown").into()));
return Err(Error::Encrypt(response.status().canonical_reason().unwrap_or("unknown").into()));
}
// read HTTP response
@@ -149,7 +149,7 @@ impl SecretStoreEncryptor {
BodyReader::new(response).read_to_string(&mut result)?;
// response is JSON string (which is, in turn, hex-encoded, encrypted Public)
let encrypted_bytes: ethjson::bytes::Bytes = result.trim_matches('\"').parse().map_err(|e| ErrorKind::Encrypt(e))?;
let encrypted_bytes: ethjson::bytes::Bytes = result.trim_matches('\"').parse().map_err(|e| Error::Encrypt(e))?;
// decrypt Public
let decrypted_bytes = self.signer.decrypt(requester, &crypto::DEFAULT_MAC, &encrypted_bytes)?;
@@ -189,7 +189,7 @@ impl SecretStoreEncryptor {
}
fn sign_contract_address(&self, contract_address: &Address) -> Result<Signature, Error> {
let key_server_account = self.config.key_server_account.ok_or_else(|| ErrorKind::KeyServerAccountNotSet)?;
let key_server_account = self.config.key_server_account.ok_or_else(|| Error::KeyServerAccountNotSet)?;
Ok(self.signer.sign(key_server_account, address_to_key(contract_address))?)
}
}
@@ -204,7 +204,7 @@ impl Encryptor for SecretStoreEncryptor {
// retrieve the key, try to generate it if it doesn't exist yet
let key = match self.retrieve_key("", false, contract_address) {
Ok(key) => Ok(key),
Err(Error(ErrorKind::EncryptionKeyNotFound(_), _)) => {
Err(Error::EncryptionKeyNotFound(_)) => {
trace!(target: "privatetx", "Key for account wasnt found in sstore. Creating. Address: {:?}", contract_address);
self.retrieve_key(&format!("/{}", self.config.threshold), true, contract_address)
}
@@ -215,7 +215,7 @@ impl Encryptor for SecretStoreEncryptor {
let mut cypher = Vec::with_capacity(plain_data.len() + initialisation_vector.len());
cypher.extend(repeat(0).take(plain_data.len()));
crypto::aes::encrypt_128_ctr(&key, initialisation_vector, plain_data, &mut cypher)
.map_err(|e| ErrorKind::Encrypt(e.to_string()))?;
.map_err(|e| Error::Encrypt(e.to_string()))?;
cypher.extend_from_slice(&initialisation_vector);
Ok(cypher)
@@ -230,7 +230,7 @@ impl Encryptor for SecretStoreEncryptor {
// initialization vector takes INIT_VEC_LEN bytes
let cypher_len = cypher.len();
if cypher_len < INIT_VEC_LEN {
bail!(ErrorKind::Decrypt("Invalid cypher".into()));
return Err(Error::Decrypt("Invalid cypher".into()));
}
// retrieve existing key
@@ -241,7 +241,7 @@ impl Encryptor for SecretStoreEncryptor {
let mut plain_data = Vec::with_capacity(cypher_len - INIT_VEC_LEN);
plain_data.extend(repeat(0).take(cypher_len - INIT_VEC_LEN));
crypto::aes::decrypt_128_ctr(&key, &iv, cypher, &mut plain_data)
.map_err(|e| ErrorKind::Decrypt(e.to_string()))?;
.map_err(|e| Error::Decrypt(e.to_string()))?;
Ok(plain_data)
}
}

View File

@@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use std::error;
use derive_more::Display;
use ethereum_types::Address;
use rlp::DecoderError;
use ethtrie::TrieError;
@@ -21,173 +23,173 @@ use ethcore::error::{Error as EthcoreError, ExecutionError};
use types::transaction::Error as TransactionError;
use ethkey::Error as KeyError;
use ethkey::crypto::Error as CryptoError;
use txpool::Error as TxPoolError;
use txpool::VerifiedTransaction;
use private_transactions::VerifiedPrivateTransaction;
error_chain! {
foreign_links {
Io(::std::io::Error) #[doc = "Error concerning the Rust standard library's IO subsystem."];
Decoder(DecoderError) #[doc = "RLP decoding error."];
Trie(TrieError) #[doc = "Error concerning TrieDBs."];
Txpool(TxPoolError) #[doc = "Tx pool error."];
Crypto(CryptoError) #[doc = "Crypto error."];
type TxPoolError = txpool::Error<<VerifiedPrivateTransaction as VerifiedTransaction>::Hash>;
#[derive(Debug, Display)]
pub enum Error {
/// Error concerning the Rust standard library's IO subsystem.
#[display(fmt = "Io Error: {}", _0)]
Io(::std::io::Error),
/// RLP decoding error.
#[display(fmt = "Decoder Error: {}", _0)]
Decoder(DecoderError),
/// Error concerning TrieDBs.
#[display(fmt = "Trie Error: {}", _0)]
Trie(TrieError),
/// Transaction pool error.
#[display(fmt = "Transaction Pool Error: {}", _0)]
TxPool(TxPoolError),
/// Crypto error.
#[display(fmt = "Crypto Error {}", _0)]
Crypto(CryptoError),
/// Encryption error.
#[display(fmt = "Encryption error. ({})", _0)]
Encrypt(String),
/// Decryption error.
#[display(fmt = "Decryption error. ({})", _0)]
Decrypt(String),
/// Address not authorized.
#[display(fmt = "Private transaction execution is not authorised for {}", _0)]
NotAuthorised(Address),
/// Transaction creates more than one contract.
#[display(fmt = "Private transaction created too many contracts")]
TooManyContracts,
/// Contract call error.
#[display(fmt = "Contract call error. ({})", _0)]
Call(String),
/// State is not available.
#[display(fmt = "State is not available")]
StatePruned,
/// State is incorrect.
#[display(fmt = "State is incorrect")]
StateIncorrect,
/// Wrong private transaction type.
#[display(fmt = "Wrong private transaction type")]
BadTransactionType,
/// Contract does not exist or was not created.
#[display(fmt = "Contract does not exist or was not created")]
ContractDoesNotExist,
/// Reference to the client is corrupted.
#[display(fmt = "Reference to the client is corrupted")]
ClientIsMalformed,
/// Queue of private transactions for verification is full.
#[display(fmt = "Queue of private transactions for verification is full")]
QueueIsFull,
/// The transaction already exists in queue of private transactions.
#[display(fmt = "The transaction already exists in queue of private transactions.")]
PrivateTransactionAlreadyImported,
/// The information about private transaction is not found in the store.
#[display(fmt = "The information about private transaction is not found in the store.")]
PrivateTransactionNotFound,
/// Account for signing public transactions not set.
#[display(fmt = "Account for signing public transactions not set.")]
SignerAccountNotSet,
/// Account for validating private transactions not set.
#[display(fmt = "Account for validating private transactions not set.")]
ValidatorAccountNotSet,
/// Account for signing requests to key server not set.
#[display(fmt = "Account for signing requests to key server not set.")]
KeyServerAccountNotSet,
/// Encryption key is not found on key server.
#[display(fmt = "Encryption key is not found on key server for {}", _0)]
EncryptionKeyNotFound(Address),
/// Key server URL is not set.
#[display(fmt = "Key server URL is not set.")]
KeyServerNotSet,
/// VM execution error.
#[display(fmt = "VM execution error {}", _0)]
Execution(ExecutionError),
/// General signing error.
#[display(fmt = "General signing error {}", _0)]
Key(KeyError),
/// Error of transactions processing.
#[display(fmt = "Error of transactions processing {}", _0)]
Transaction(TransactionError),
/// General ethcore error.
#[display(fmt = "General ethcore error {}", _0)]
Ethcore(EthcoreError),
/// A convenient variant for String.
#[display(fmt = "{}", _0)]
Msg(String),
}
impl error::Error for Error {
fn source(&self) -> Option<&(error::Error + 'static)> {
match self {
Error::Io(e) => Some(e),
Error::Decoder(e) => Some(e),
Error::Trie(e) => Some(e),
Error::TxPool(e) => Some(e),
Error::Crypto(e) => Some(e),
Error::Execution(e) => Some(e),
Error::Key(e) => Some(e),
Error::Transaction(e) => Some(e),
Error::Ethcore(e) => Some(e),
_ => None,
}
}
}
errors {
#[doc = "Encryption error."]
Encrypt(err: String) {
description("Encryption error"),
display("Encryption error. ({})", err),
}
impl From<String> for Error {
fn from(s: String) -> Self {
Error::Msg(s)
}
}
#[doc = "Decryption error."]
Decrypt(err: String) {
description("Decryption error"),
display("Decryption error. ({})", err),
}
#[doc = "Address not authorized."]
NotAuthorised(address: Address) {
description("Address not authorized"),
display("Private transaction execution is not authorised for {}", address),
}
#[doc = "Transaction creates more than one contract."]
TooManyContracts {
description("Transaction creates more than one contract."),
display("Private transaction created too many contracts"),
}
#[doc = "Contract call error."]
Call(err: String) {
description("Contract call error."),
display("Contract call error. ({})", err),
}
#[doc = "State is not available."]
StatePruned {
description("State is not available."),
display("State is not available"),
}
#[doc = "State is incorrect."]
StateIncorrect {
description("State is incorrect."),
display("State is incorrect"),
}
#[doc = "Wrong private transaction type."]
BadTransactionType {
description("Wrong private transaction type."),
display("Wrong private transaction type"),
}
#[doc = "Contract does not exist or was not created."]
ContractDoesNotExist {
description("Contract does not exist or was not created."),
display("Contract does not exist or was not created"),
}
#[doc = "Reference to the client is corrupted."]
ClientIsMalformed {
description("Reference to the client is corrupted."),
display("Reference to the client is corrupted"),
}
#[doc = "Queue of private transactions for verification is full."]
QueueIsFull {
description("Queue of private transactions for verification is full."),
display("Queue of private transactions for verification is full"),
}
#[doc = "The transaction already exists in queue of private transactions."]
PrivateTransactionAlreadyImported {
description("The transaction already exists in queue of private transactions."),
display("The transaction already exists in queue of private transactions."),
}
#[doc = "The information about private transaction is not found in the store."]
PrivateTransactionNotFound {
description("The information about private transaction is not found in the store."),
display("The information about private transaction is not found in the store."),
}
#[doc = "Account for signing public transactions not set."]
SignerAccountNotSet {
description("Account for signing public transactions not set."),
display("Account for signing public transactions not set."),
}
#[doc = "Account for validating private transactions not set."]
ValidatorAccountNotSet {
description("Account for validating private transactions not set."),
display("Account for validating private transactions not set."),
}
#[doc = "Account for signing requests to key server not set."]
KeyServerAccountNotSet {
description("Account for signing requests to key server not set."),
display("Account for signing requests to key server not set."),
}
#[doc = "Encryption key is not found on key server."]
EncryptionKeyNotFound(address: Address) {
description("Encryption key is not found on key server"),
display("Encryption key is not found on key server for {}", address),
}
#[doc = "Key server URL is not set."]
KeyServerNotSet {
description("Key server URL is not set."),
display("Key server URL is not set."),
}
#[doc = "VM execution error."]
Execution(err: ExecutionError) {
description("VM execution error."),
display("VM execution error {}", err),
}
#[doc = "General signing error."]
Key(err: KeyError) {
description("General signing error."),
display("General signing error {}", err),
}
#[doc = "Error of transactions processing."]
Transaction(err: TransactionError) {
description("Error of transactions processing."),
display("Error of transactions processing {}", err),
}
#[doc = "General ethcore error."]
Ethcore(err: EthcoreError) {
description("General ethcore error."),
display("General ethcore error {}", err),
}
impl From<std::io::Error> for Error {
fn from(err: std::io::Error) -> Self {
Error::Io(err).into()
}
}
impl From<KeyError> for Error {
fn from(err: KeyError) -> Self {
ErrorKind::Key(err).into()
Error::Key(err).into()
}
}
impl From<CryptoError> for Error {
fn from(err: CryptoError) -> Self {
Error::Crypto(err).into()
}
}
impl From<DecoderError> for Error {
fn from(err: DecoderError) -> Self {
Error::Decoder(err).into()
}
}
impl From<ExecutionError> for Error {
fn from(err: ExecutionError) -> Self {
ErrorKind::Execution(err).into()
Error::Execution(err).into()
}
}
impl From<TransactionError> for Error {
fn from(err: TransactionError) -> Self {
ErrorKind::Transaction(err).into()
Error::Transaction(err).into()
}
}
impl From<TrieError> for Error {
fn from(err: TrieError) -> Self {
Error::Trie(err).into()
}
}
impl From<TxPoolError> for Error {
fn from(err: TxPoolError) -> Self {
Error::TxPool(err).into()
}
}
impl From<EthcoreError> for Error {
fn from(err: EthcoreError) -> Self {
ErrorKind::Ethcore(err).into()
Error::Ethcore(err).into()
}
}

View File

@@ -54,8 +54,7 @@ extern crate log;
extern crate ethabi_derive;
#[macro_use]
extern crate ethabi_contract;
#[macro_use]
extern crate error_chain;
extern crate derive_more;
#[macro_use]
extern crate rlp_derive;
@@ -68,7 +67,7 @@ pub use encryptor::{Encryptor, SecretStoreEncryptor, EncryptorConfig, NoopEncryp
pub use key_server_keys::{KeyProvider, SecretStoreKeys, StoringKeyProvider};
pub use private_transactions::{VerifiedPrivateTransaction, VerificationStore, PrivateTransactionSigningDesc, SigningStore};
pub use messages::{PrivateTransaction, SignedPrivateTransaction};
pub use error::{Error, ErrorKind};
pub use error::Error;
use std::sync::{Arc, Weak};
use std::collections::{HashMap, HashSet, BTreeMap};
@@ -238,10 +237,10 @@ impl Provider {
trace!(target: "privatetx", "Creating private transaction from regular transaction: {:?}", signed_transaction);
if self.signer_account.is_none() {
warn!(target: "privatetx", "Signing account not set");
bail!(ErrorKind::SignerAccountNotSet);
return Err(Error::SignerAccountNotSet);
}
let tx_hash = signed_transaction.hash();
let contract = Self::contract_address_from_transaction(&signed_transaction).map_err(|_| ErrorKind::BadTransactionType)?;
let contract = Self::contract_address_from_transaction(&signed_transaction).map_err(|_| Error::BadTransactionType)?;
let data = signed_transaction.rlp_bytes();
let encrypted_transaction = self.encrypt(&contract, &Self::iv_from_transaction(&signed_transaction), &data)?;
let private = PrivateTransaction::new(encrypted_transaction, contract);
@@ -278,13 +277,12 @@ impl Provider {
fn pool_client<'a>(&'a self, nonce_cache: &'a NonceCache, local_accounts: &'a HashSet<Address>) -> miner::pool_client::PoolClient<'a, Client> {
let engine = self.client.engine();
let refuse_service_transactions = true;
miner::pool_client::PoolClient::new(
&*self.client,
nonce_cache,
engine,
local_accounts,
refuse_service_transactions,
None, // refuse_service_transactions = true
)
}
@@ -309,19 +307,19 @@ impl Provider {
// TODO #9825 [ToDr] Usage of BlockId::Latest
let contract_nonce = self.get_contract_nonce(&contract, BlockId::Latest);
if let Err(e) = contract_nonce {
bail!("Cannot retrieve contract nonce: {:?}", e);
return Err(format!("Cannot retrieve contract nonce: {:?}", e).into());
}
let contract_nonce = contract_nonce.expect("Error was checked before");
let private_state = self.execute_private_transaction(BlockId::Latest, &transaction.transaction);
if let Err(e) = private_state {
bail!("Cannot retrieve private state: {:?}", e);
return Err(format!("Cannot retrieve private state: {:?}", e).into());
}
let private_state = private_state.expect("Error was checked before");
let private_state_hash = self.calculate_state_hash(&private_state, contract_nonce);
trace!(target: "privatetx", "Hashed effective private state for validator: {:?}", private_state_hash);
let signed_state = self.accounts.sign(validator_account, private_state_hash);
if let Err(e) = signed_state {
bail!("Cannot sign the state: {:?}", e);
return Err(format!("Cannot sign the state: {:?}", e).into());
}
let signed_state = signed_state.expect("Error was checked before");
let signed_private_transaction = SignedPrivateTransaction::new(private_hash, signed_state, None);
@@ -362,25 +360,27 @@ impl Provider {
signatures.push(signed_tx.signature());
let rsv: Vec<Signature> = signatures.into_iter().map(|sign| sign.into_electrum().into()).collect();
// Create public transaction
let signer_account = self.signer_account.ok_or_else(|| Error::SignerAccountNotSet)?;
let state = self.client.state_at(BlockId::Latest).ok_or(Error::StatePruned)?;
let nonce = state.nonce(&signer_account)?;
let public_tx = self.public_transaction(
desc.state.clone(),
&desc.original_transaction,
&rsv,
desc.original_transaction.nonce,
nonce,
desc.original_transaction.gas_price
)?;
trace!(target: "privatetx", "Last required signature received, public transaction created: {:?}", public_tx);
// Sign and add it to the queue
let chain_id = desc.original_transaction.chain_id();
let hash = public_tx.hash(chain_id);
let signer_account = self.signer_account.ok_or_else(|| ErrorKind::SignerAccountNotSet)?;
let signature = self.accounts.sign(signer_account, hash)?;
let signed = SignedTransaction::new(public_tx.with_signature(signature, chain_id))?;
match self.miner.import_own_transaction(&*self.client, signed.into()) {
Ok(_) => trace!(target: "privatetx", "Public transaction added to queue"),
Err(err) => {
warn!(target: "privatetx", "Failed to add transaction to queue, error: {:?}", err);
bail!(err);
return Err(err.into());
}
}
// Notify about state changes
@@ -395,7 +395,7 @@ impl Provider {
// Remove from store for signing
if let Err(err) = self.transactions_for_signing.write().remove(&private_hash) {
warn!(target: "privatetx", "Failed to remove transaction from signing store, error: {:?}", err);
bail!(err);
return Err(err);
}
} else {
// Add signature to the store
@@ -403,7 +403,7 @@ impl Provider {
Ok(_) => trace!(target: "privatetx", "Signature stored for private transaction"),
Err(err) => {
warn!(target: "privatetx", "Failed to add signature to signing store, error: {:?}", err);
bail!(err);
return Err(err);
}
}
}
@@ -415,7 +415,7 @@ impl Provider {
Action::Call(contract) => Ok(contract),
_ => {
warn!(target: "privatetx", "Incorrect type of action for the transaction");
bail!(ErrorKind::BadTransactionType);
return Err(Error::BadTransactionType);
}
}
}
@@ -434,13 +434,13 @@ impl Provider {
}
false => {
warn!(target: "privatetx", "Sender's state doesn't correspond to validator's");
bail!(ErrorKind::StateIncorrect);
return Err(Error::StateIncorrect);
}
}
}
Err(err) => {
warn!(target: "privatetx", "Sender's state doesn't correspond to validator's, error {:?}", err);
bail!(err);
return Err(err.into());
}
}
}
@@ -480,21 +480,21 @@ impl Provider {
fn get_decrypted_state(&self, address: &Address, block: BlockId) -> Result<Bytes, Error> {
let (data, decoder) = private_contract::functions::state::call();
let value = self.client.call_contract(block, *address, data)?;
let state = decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?;
let state = decoder.decode(&value).map_err(|e| Error::Call(format!("Contract call failed {:?}", e)))?;
self.decrypt(address, &state)
}
fn get_decrypted_code(&self, address: &Address, block: BlockId) -> Result<Bytes, Error> {
let (data, decoder) = private_contract::functions::code::call();
let value = self.client.call_contract(block, *address, data)?;
let state = decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?;
let state = decoder.decode(&value).map_err(|e| Error::Call(format!("Contract call failed {:?}", e)))?;
self.decrypt(address, &state)
}
pub fn get_contract_nonce(&self, address: &Address, block: BlockId) -> Result<U256, Error> {
let (data, decoder) = private_contract::functions::nonce::call();
let value = self.client.call_contract(block, *address, data)?;
decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)).into())
decoder.decode(&value).map_err(|e| Error::Call(format!("Contract call failed {:?}", e)).into())
}
fn snapshot_to_storage(raw: Bytes) -> HashMap<H256, H256> {
@@ -531,10 +531,10 @@ impl Provider {
T: Tracer,
V: VMTracer,
{
let mut env_info = self.client.env_info(block).ok_or(ErrorKind::StatePruned)?;
let mut env_info = self.client.env_info(block).ok_or(Error::StatePruned)?;
env_info.gas_limit = transaction.gas;
let mut state = self.client.state_at(block).ok_or(ErrorKind::StatePruned)?;
let mut state = self.client.state_at(block).ok_or(Error::StatePruned)?;
// TODO #9825 in case of BlockId::Latest these need to operate on the same state
let contract_address = match transaction.action {
Action::Call(ref contract_address) => {
@@ -610,15 +610,15 @@ impl Provider {
/// Create encrypted public contract deployment transaction.
pub fn public_creation_transaction(&self, block: BlockId, source: &SignedTransaction, validators: &[Address], gas_price: U256) -> Result<(Transaction, Address), Error> {
if let Action::Call(_) = source.action {
bail!(ErrorKind::BadTransactionType);
return Err(Error::BadTransactionType);
}
let sender = source.sender();
let state = self.client.state_at(block).ok_or(ErrorKind::StatePruned)?;
let state = self.client.state_at(block).ok_or(Error::StatePruned)?;
let nonce = state.nonce(&sender)?;
let executed = self.execute_private(source, TransactOptions::with_no_tracing(), block)?;
let header = self.client.block_header(block)
.ok_or(ErrorKind::StatePruned)
.and_then(|h| h.decode().map_err(|_| ErrorKind::StateIncorrect).into())?;
.ok_or(Error::StatePruned)
.and_then(|h| h.decode().map_err(|_| Error::StateIncorrect).into())?;
let (executed_code, executed_state) = (executed.code.unwrap_or_default(), executed.state);
let tx_data = Self::generate_constructor(validators, executed_code.clone(), executed_state.clone());
let mut tx = Transaction {
@@ -649,7 +649,7 @@ impl Provider {
/// Create encrypted public contract deployment transaction. Returns updated encrypted state.
pub fn execute_private_transaction(&self, block: BlockId, source: &SignedTransaction) -> Result<Bytes, Error> {
if let Action::Create = source.action {
bail!(ErrorKind::BadTransactionType);
return Err(Error::BadTransactionType);
}
let result = self.execute_private(source, TransactOptions::with_no_tracing(), block)?;
Ok(result.state)
@@ -678,7 +678,7 @@ impl Provider {
pub fn get_validators(&self, block: BlockId, address: &Address) -> Result<Vec<Address>, Error> {
let (data, decoder) = private_contract::functions::get_validators::call();
let value = self.client.call_contract(block, *address, data)?;
decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)).into())
decoder.decode(&value).map_err(|e| Error::Call(format!("Contract call failed {:?}", e)).into())
}
fn get_contract_version(&self, block: BlockId, address: &Address) -> usize {

View File

@@ -28,7 +28,7 @@ use parking_lot::RwLock;
use types::transaction::{UnverifiedTransaction, SignedTransaction};
use txpool;
use txpool::{VerifiedTransaction, Verifier};
use error::{Error, ErrorKind};
use error::Error;
type Pool = txpool::Pool<VerifiedPrivateTransaction, pool::scoring::NonceAndGasPrice>;
@@ -154,7 +154,7 @@ impl Default for VerificationStore {
impl VerificationStore {
/// Adds private transaction for verification into the store
pub fn add_transaction<C: pool::client::Client>(
pub fn add_transaction<C: pool::client::Client + pool::client::NonceClient + Clone>(
&self,
transaction: UnverifiedTransaction,
validator_account: Option<Address>,
@@ -164,7 +164,7 @@ impl VerificationStore {
let options = self.verification_options.clone();
// Use pool's verifying pipeline for original transaction's verification
let verifier = pool::verifier::Verifier::new(client, options, Default::default(), None);
let verifier = pool::verifier::Verifier::new(client.clone(), options, Default::default(), None);
let unverified = pool::verifier::Transaction::Unverified(transaction);
let verified_tx = verifier.verify_transaction(unverified)?;
let signed_tx: SignedTransaction = verified_tx.signed().clone();
@@ -177,8 +177,9 @@ impl VerificationStore {
transaction_hash: signed_hash,
transaction_sender: signed_sender,
};
let mut pool = self.verification_pool.write();
pool.import(verified)?;
let replace = pool::replace::ReplaceByScoreAndReadiness::new(
self.verification_pool.read().scoring().clone(), client);
self.verification_pool.write().import(verified, &replace)?;
Ok(())
}
@@ -228,7 +229,7 @@ impl SigningStore {
contract_nonce: U256,
) -> Result<(), Error> {
if self.transactions.len() > MAX_QUEUE_LEN {
bail!(ErrorKind::QueueIsFull);
return Err(Error::QueueIsFull);
}
self.transactions.insert(private_hash, PrivateTransactionSigningDesc {
@@ -254,7 +255,7 @@ impl SigningStore {
/// Adds received signature for the stored private transaction
pub fn add_signature(&mut self, private_hash: &H256, signature: Signature) -> Result<(), Error> {
let desc = self.transactions.get_mut(private_hash).ok_or_else(|| ErrorKind::PrivateTransactionNotFound)?;
let desc = self.transactions.get_mut(private_hash).ok_or_else(|| Error::PrivateTransactionNotFound)?;
if !desc.received_signatures.contains(&signature) {
desc.received_signatures.push(signature);
}

View File

@@ -8,11 +8,12 @@
"difficultyBoundDivisor": "0x0800",
"durationLimit": "0x0d",
"blockReward": "0x4563918244F40000",
"homesteadTransition": 1150000,
"ecip1010PauseTransition": 3000000,
"ecip1010ContinueTransition": 5000000,
"ecip1017EraRounds": 5000000,
"bombDefuseTransition": 5900000
"homesteadTransition": "0x118c30",
"ecip1010PauseTransition": "0x2dc6c0",
"ecip1010ContinueTransition": "0x4c4b40",
"ecip1017EraRounds": "0x4c4b40",
"eip100bTransition": "0x7fffffffffffffff",
"bombDefuseTransition": "0x5a06e0"
}
}
},
@@ -26,11 +27,17 @@
"chainID": "0x3d",
"forkBlock": "0x1d4c00",
"forkCanonHash": "0x94365e3a8c0b35089c1d1195081fe7489b528a84b22199c916180db8b28ade7f",
"eip150Transition": 2500000,
"eip160Transition": 3000000,
"eip150Transition": "0x2625a0",
"eip160Transition": "0x2dc6c0",
"eip161abcTransition": "0x7fffffffffffffff",
"eip161dTransition": "0x7fffffffffffffff",
"eip155Transition": 3000000
"eip155Transition": "0x2dc6c0",
"maxCodeSize": "0x6000",
"maxCodeSizeTransition": "0x7fffffffffffffff",
"eip140Transition": "0x7fffffffffffffff",
"eip211Transition": "0x7fffffffffffffff",
"eip214Transition": "0x7fffffffffffffff",
"eip658Transition": "0x7fffffffffffffff"
},
"genesis": {
"seal": {
@@ -48,8 +55,8 @@
"stateRoot": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544"
},
"hardcodedSync": {
"header": "f90210a08eb792fdb134b57fffbdf19bd61d4c1cc351fc38a7fcf6609c82b35ea364208fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794df7d7e053933b5cc24372f878c90e62dadad5d42a0e29a2e741354b453139d244920f7d552f90a579f1dcb99ef6b470bcffc713ebaa04bb64c992b8cf56259177a192d6f0a1eddf192b8daa7dbf1ec8313428cccde20a0ee22efe3b124a0297503fd26e6f7b33c7a88aa75825259297f8e30bee3632a68b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000866a396ffc14908373480183797a1182f618845c7395609165746865726d696e652d6574632d757331a087f3616cc0ba3704e23702bf7461f8f7716f1f1ad3ac4c66391d45adc57d1dea886ecb8e800fe87049",
"totalDifficulty": "575603227549295900024",
"header": "f9021ba0a281d23475d3d5ff03df8636c9f528cdd91498af274a3b2f8989bbd51bfeb809a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794004730417cd2b1d19f6be2679906ded4fa8a64e2a0d5fdd62e7e29dc3da1cd3fe5ad549e000260bfdb55f523fde008f26390220d23a0370ff78457d6c7469ff333a13165f4bb8057d00cfa68365cb4d1a8c8a1da46d5a0dea37365a20f5bb5ad3766a24a9fe7b04b946e35aaba74f862467a7c5cdb7d67b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000004000000000040000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000100000000000000000000000080000000000000000020000000000000000000000000000000000000000000000000000000000000000000000020000000000001000000000000000000000000000000080010000000000000008000000000000000866fc181925a9783763801837a121d830c317c845c9d1efe9b457468657265756d436c6173736963534f4c4f2f326d696e657273a0bb6e626c7ee3d827da18e1b303d9552ba17e92cefcedfc58bdfc5bac6a8ebabe882d8c26402344c24b",
"totalDifficulty": "598584828374329723203",
"CHTs": [
"0x0eb474b7721727204978e92e27d31cddff56471911e424a4c8271c35f9c982cc",
"0xe10e94515fb5ffb7ffa9bf50db4a959b3f50c2ff75e0b8bd5f5e038749e52a11",
@@ -3739,9 +3746,103 @@
"0x362ca494021482f0d9dea4abd844ca11b71fbeb0a98e7db7bfb3bb6f864eb58c",
"0x09ec27c856f50888e4634ffaca66f8185fd13e0bb2bbf522ce6209886502c7a5",
"0x24996d2f96618887c1c5e61d5d7ce6948853ca35811d48f72155a4778308e255",
"0x4f199a8efc8615c623902b5c279dd995ac1df4654a07aab0423e070d14bd24d0"
"0x4f199a8efc8615c623902b5c279dd995ac1df4654a07aab0423e070d14bd24d0",
"0xe6875990cef0d2ce1f9d100654cdf522bbe345a462ebca769b1e288128c13201",
"0x36c141d47991e557f7226d8b1fe791c334f046f867d7865d663f99e2a337d915",
"0x337e59da56cde8e3f9e90fafff54d4fa240ba01aec855fd55626e4b3a45a9767",
"0x67672d3a29c49e3545d25422b6015a1eebe86596f55d4c9b8772e89c99ac9f8b",
"0x6d6e167641bcd2e5241ac2710951f7f0c47fb311e32e998831e6fe38f5bebb25",
"0x6dc4fa5ae3f281a90619216491284d951151f37be648694d1952314f43ffe05d",
"0x3c865ccee7900b39d671c43ae15df71fad294781d74815537de94d02b48dd8a0",
"0x10ba37d2ff46db181ff8a15f38bfeecfd9c21e28bf63cb5ab975a2d7c74c0aef",
"0xba265a598f3af5bf4c2b87bd8d28a55f963cfbd09108aaccd5b00294f662e8b9",
"0xaab422eb98f7b0ab9a01558069a3666efa2be2510097b0054bd5c8fceb1023df",
"0xdbff3ce1e6fb0388029f95bd091c95b88c6539fabfe6f1de8e44c47dab064ff8",
"0xb1aa0c7254f3aaa61b58c9d973f3d89f5f4dc6bfee011ad4c4a3e3ae76aaf7df",
"0x055e36325029db9e089808ca01b0ee3eae53703f3e91ee51e587e7b7dcaa8a3d",
"0x00ec5a25517cf0c0a1bf892e5209fd0185ff1ffc6b2523642bf86f6a3d0c10f3",
"0x7bc6a8d5017760f12ace9ebfcdf5a91abcfd6e4f4131df5c4dbe84d2d6a6add9",
"0xeb5da64c8d0cc93a44da96ee9c3c0a22054a2a2e87a7491a5618ade1f59a1b96",
"0xc0a937729678bb6aca27ae16c662ccd2dd0b53346c610d6e5d5b1655762fa4b3",
"0x55c732917d3894ffeb9844fcb1c690d0956c4e2a8eccb6552cdde4ea90c99db2",
"0xf1dfd2205daf748da9e8e98bc4ee94cd6b2db5560e4cead28910e14c576337aa",
"0x60a271fb20c017f90d99c57783ebb8b1a3233398c49f89d73db14b09adf2893b",
"0x8fbd97d55dc64f2124c79054765515f49d79a05f2962b17875f12b353c33f564",
"0x5afd5951c5e834fbf22071047f72619496e9a9dbc6073b661c44741b67fabf03",
"0x2d05a19223820f92e385d2c942b70cca32804546f3aa7058381ca3f6c1ecde11",
"0x267dab323804f2e7bdcc80dde83ccbff56d1aa0fffd0edc7c02ffd4a24bbe027",
"0xf4e9e580bbcc5a9be1f942c12d4b34eb1a4c07feffd0b95abe27ddff57a6cc8f",
"0x3f146ceffcd100ca9fc1af743fad74acd03a289f4038413acfcfd0eb87d14a56",
"0xef98171ed6b269c0ebd6bdbb1d98694316b639bae6a3ad01f4964c3d2eb3d2cf",
"0x510013a35d5c71863b3385176c794ad90e17af1fd271b933f9f7ab980311b27c",
"0x5eb181d22f30ed203c4d3fad610d31c2338dae6a88eee250af19ae0f58319ad1",
"0x50a28d65b51ff086dcf2110feca7d990db95f078394c56bfb850a3b8cfd7f1a2",
"0x4148b8f2136b84773b7ff71d73aa8ffb98f0f3952939849f324c28b9173efd70",
"0xa980bc7fa736bf6d6d794ffa5e035664c45117c21e40da7ba76de7c2ff8164d0",
"0x794a8ef17e48986df700d6e68799a50695086702d6224ae9a71663fd03f8a55e",
"0xf354c82e1c75d7d758099dcd4d0592363eef81e85cba773aa6d6b30e1900582a",
"0xbb4c8b990add1c4e43ddebf742eb605028ae2daa8b61db7d237386d81e4c3413",
"0x61470a53ef9757fa7c452bdbe26d448dd8bf6590fc11420ebeddf441fe56f381",
"0x603558b2f72405e9625ac561d62c2bbcdda84d8ef4b5510d06bdac0553025bf2",
"0xf52d9ba6ba149d0e4266a8d05b73e4a445e9583560024e0185d4b8b12bd55640",
"0x26ef211f77b4a67ddb0a24c4e63f7d247d6ce8635dd9862894bdc067633ff395",
"0xed4ce5eb08b63534c5de241513a996322d168f6b8bf5c75167e79dd7ca1cc817",
"0x9d5f39f494a36d17db609b7a7a62734ca7222426c3556132bf1e2241d6c45cd2",
"0xe664772da4521e1140cc2c5db744010f57c15374dfb78a97701904787846a8f6",
"0x93faea0d197923b1578ac190fe608203f637fe4991ad4954c15ea94e17ee948b",
"0x2b028c1aaae5217cabb97c46c20541c93e55a868f78e82740f9fb9a0a033d662",
"0x529103419484990ad11c05e0c4c696826f67fbcd491e19aaac461cc340747ec4",
"0xc1e773415513b7bf47340d7b0a29e5d49d1a88bb3d0ee2a79726169d32012378",
"0xf97c43bb4ae25524b180e59cb6cac75858d4a8a0772fcf4f3bd24dfad42169da",
"0x19fa7ad12455fd022cfd15897d553e031ca1adf80c963c770250d36f1810a5f0",
"0xe67ce6e2444b8318a01150952a537ee47b701555c79f60eb90d3c3cdf93fb6b1",
"0x1b49d232180b0922704ebd4e9fabca5dd8ae9cfc2a39ea07226ba903a15037e3",
"0x56540b02ffe1743468342b5664b6e51cb3ef6c48dd74d6cd74e0c0c513c13129",
"0xd4d9d67f352c7f54d68ce994b3765b032108a5bd0b5b62d14b893949b96008d4",
"0x44d1b765df81594fd37e7700019f19b1ebd6d9b50631455931b83ce35238cb6b",
"0x2b67aef7cecfec055853cd63e8519bf506d7a1ae69a768e4db9415bdff532c47",
"0xc30ac2a4acc33cec2cdc83e114fb8237c4900a2fc89dddb6af3a4dd5e4868e51",
"0xe0e7127e086e2011f30fcd0469b35769cae163acb8ee6db8a8e2c032c2b351c5",
"0xb46c428070d15ec926fdf1d7465a9168c56dbb959d5391e26480500a98e36047",
"0x8dab41ce167633da3c0b5332833dfad5d2c28ef30c94973e5f4647e312781676",
"0xc632d30657b39208c254cf4f899d00d7c3196cbdc31248798a760972bf399fec",
"0xb4eb2c6c656406a9bc6cc6176dbdfc0e878046530d830a51e04a4e22c4572370",
"0xadb48a02c9c87b246360edb45528ba23cceed736a2ee0cfd03177428e6243024",
"0x443ac2e63e6d629398e607d6689725dd68fd5254916c1b76c876885456a13338",
"0xb66c4d950a9304025654de37c7d0e9759b755d86226a816d1e3b4c7d654a1bc3",
"0xded624610c3493bc7806844342c37909c1c1d179025c215108a12a0428ae9e36",
"0x28c85177961714ce796f152dcd31c8b19db1c39deebfe383d6fdf2334d4261b6",
"0x6d342534c3a4a875c5455ed3ef546e876cedb5aee7b2ecf194c6e47c6a09d3a4",
"0x65a84879e014085b7a0de5bf604050bc6bffd8ab7748253203fff49573763558",
"0xcb0e4339dfbfc8b420c915149a0d352fda69c31668b32452c432f067462b4325",
"0x3466440e4c88895f2642f2986dea4be482c028592530224d73e67254b2bac69f",
"0xb7c325fec25c7b278724ebb91c64fc2ac37e91e44b136dd6c29bf48b80990888",
"0x7a9a2bd3ab5972c1a4ec5972f959a1e30eb678090ed76947e38d76fc3ed758a5",
"0x74deabf896026cb20e2f5f8a88828b265d6696883dab972fe1bc9a4ca98d68b5",
"0x195d2e25b1ec8deea095bcbaac5277f4586237e68bd9c9ad24e65a8e53d6d27a",
"0xcc343c21f7f18c1d507cc3cf12381d7bbe55d7355363361d05d972343fb4b7fe",
"0xd2637aaef2034203e549453225eb1d75633d2c66e8cad0419395250c1e369536",
"0x0f8052a87aa435deee2826e6dbc944128835264d5770dbb064373de05333f8c2",
"0x2091278a3d6a7ed1ab0458cc307903a51d75c6a1c549ebed1f0aed29ce6533b8",
"0x3f7d25feee0dcf39372ccbad55989442d9b7ce16ac93e4b1dca63bd92d5204e4",
"0xd0f866c38597038e360af960e3e84c79a0027576bf3fdf4358a9442f0c671b61",
"0xc527b3694dc6b46f0562cb36e2f766e5b75793ad2794258d8be5119bff4ea8b0",
"0x47f1d7d32904cb0945e97140c2412d12b1e0980c2f72c7878250170aae4124dd",
"0x57aa1ef2a7ec01ee7acd0c4baed5407f30d6c34f2bc6bce7fda6366517343199",
"0xd392127f856736dd74d16a24309a247682e2736f78fc92713c484a6f13edcdbf",
"0x595aa7e3eddba867389d63b2eaa6b16e4e5163076f03d2c8013e40c3b0fc98c0",
"0x50bb320d8bea03db548be3a3b619159e1993ba8eea83af6f022b9cd29ae4d0ff",
"0x53deeb64ee923912f76a233532f474d76d8f6b8cc42eedcce81bda8ad608294c",
"0x1af301b0eaf36d16a74b2d1f76e9e26659f047cd3466a765049260047c25bbee",
"0x05c1d40227ece15c55f06dc922f5a9be01cc147a96e070e7a81b696f0f40b6ee",
"0xa63ee877c70d8e51e795d153a34ce3bcc212f8fb8e77df52ff83084b9133a280",
"0x07ab3e2107db7ff479f5be0d7a57e3b76627cf6230cdeb61d78ebaa2c391d360",
"0xc893aee6d249c152f5db3d7763f34a3311345dff721ae9c71ab5fb3d2b3e2559",
"0x250caa98ea3e682be9c866990f19647f443d57690052229ac0ccfa0ab30a5a71",
"0xc32fd5318214071a41cd8e98499b2b65942c5837c686a06b536146fd0bf294bf",
"0xac390c012eecd83fa8f4cc77a59992914b5c95af36b28747e07adea13228acbc"
]
},
},
"nodes": [
"enode://efd48ad0879eeb7f9cb5e50f33f7bc21e805a72e90361f145baaa22dd75d111e7cd9c93f1b7060dcb30aa1b3e620269336dbf32339fea4c18925a4c15fe642df@18.205.66.229:30303",
"enode://5fbfb426fbb46f8b8c1bd3dd140f5b511da558cd37d60844b525909ab82e13a25ee722293c829e52cb65c2305b1637fa9a2ea4d6634a224d5f400bfe244ac0de@162.243.55.45:30303",
@@ -3757,10 +3858,97 @@
"enode://5cd218959f8263bc3721d7789070806b0adff1a0ed3f95ec886fb469f9362c7507e3b32b256550b9a7964a23a938e8d42d45a0c34b332bfebc54b29081e83b93@35.187.57.94:30303"
],
"accounts": {
"0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
"0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
"0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
"0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
"0x0000000000000000000000000000000000000001": {
"builtin": {
"name": "ecrecover",
"pricing": {
"linear": {
"base": 3000,
"word": 0
}
}
}
},
"0x0000000000000000000000000000000000000002": {
"builtin": {
"name": "sha256",
"pricing": {
"linear": {
"base": 60,
"word": 12
}
}
}
},
"0x0000000000000000000000000000000000000003": {
"builtin": {
"name": "ripemd160",
"pricing": {
"linear": {
"base": 600,
"word": 120
}
}
}
},
"0x0000000000000000000000000000000000000004": {
"builtin": {
"name": "identity",
"pricing": {
"linear": {
"base": 15,
"word": 3
}
}
}
},
"0x0000000000000000000000000000000000000005": {
"builtin": {
"name": "modexp",
"activate_at": "0x7fffffffffffffff",
"pricing": {
"modexp": {
"divisor": 20
}
}
}
},
"0x0000000000000000000000000000000000000006": {
"builtin": {
"name": "alt_bn128_add",
"activate_at": "0x7fffffffffffffff",
"pricing": {
"linear": {
"base": 500,
"word": 0
}
}
}
},
"0x0000000000000000000000000000000000000007": {
"builtin": {
"name": "alt_bn128_mul",
"activate_at": "0x7fffffffffffffff",
"pricing": {
"linear": {
"base": 40000,
"word": 0
}
}
}
},
"0x0000000000000000000000000000000000000008": {
"builtin": {
"name": "alt_bn128_pairing",
"activate_at": "0x7fffffffffffffff",
"pricing": {
"alt_bn128_pairing": {
"base": 100000,
"pair": 80000
}
}
}
},
"3282791d6fd713f1e94f4bfd565eaa78b3a0599d": {
"balance": "1337000000000000000000"
},

View File

@@ -1,87 +0,0 @@
{
"name": "Easthub",
"dataDir": "easthub",
"engine": {
"Ethash": {
"params": {
"minimumDifficulty": "0x020000",
"difficultyBoundDivisor": "0x0800",
"durationLimit": "0x0d",
"blockReward": "0x2B5E3AF16B1880000",
"homesteadTransition": "0x0",
"bombDefuseTransition": "0x0",
"ecip1017EraRounds": 5000000
}
}
},
"params": {
"gasLimitBoundDivisor": "0x0400",
"registrar": "0x0000000000000000000000000000000000000000",
"accountStartNonce": "0x00",
"maximumExtraDataSize": "0x20",
"minGasLimit": "0x1388",
"networkID": "0x7",
"chainID": "0x7",
"eip150Transition": "0x0",
"eip160Transition": "0x0",
"eip155Transition": "0x0",
"eip161abcTransition": "0x7fffffffffffffff",
"eip161dTransition": "0x7fffffffffffffff"
},
"genesis": {
"seal": {
"ethereum": {
"nonce": "0x0000000000000042",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
},
"difficulty": "0x0400000000",
"author": "0x0000000000000000000000000000000000000000",
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x323031382045617374636f696e2050726f6a656374",
"gasLimit": "0x1388"
},
"nodes": [
"enode://ca57e40edb95a08a81b85a91e91099a0aaab777ad329ea7f3f772bc0fd511a276a5d84944725d181ff80f8c7dc1034814bff25b9723b03363d48617fed4b15f0@13.125.109.174:30303",
"enode://57254e23a7e5fe1e081ee5d1b236e37735a120660daeb4bf1fec6943a82c915c5b6fad23eeb1a43a27c23f236e084e8051aaa28f7d4139149f844747facb62bb@18.217.39.51:30303",
"enode://ef248f327c73c0318f4d51a62270b0612f3c4a4fd04b77d04854dc355980e137708d1e48811bc91387b0d7eb85cf447d8bbc095404f39bb7064e76751bda9cd4@52.221.160.236:30303",
"enode://bf6f0e37dd733cf04f2b079c753d2dea7cc7c59d8637eff9a8e63e17d08e2bfc91229fbb2dff08fe6ee12e51c1b6f8ed969d7042b89d77029e7ea02b05e17be3@18.197.47.177:30303"
],
"accounts": {
"0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
"0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
"0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
"0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
"20c1252a8cb33a7a9a257b2a4cfeed8daf87c847": {
"balance": "100000000000000000000000000"
},
"9dcd37c8e5aea3a0d37c5d0a2db683362d81febd": {
"balance": "100000000000000000000000000"
},
"9eff080302333f44a60bfd8c33bd63015c6d921b": {
"balance": "100000000000000000000000000"
},
"c1df2e5de98d5c41fec0642dc302971f5d3500bd": {
"balance": "100000000000000000000000000"
},
"2e0fb67cd1d029cbaea4b74c361efcc06b3105fd": {
"balance": "100000000000000000000000000"
},
"2b6425cc3cd90654f077889ef7262ac2f5846460": {
"balance": "100000000000000000000000000"
},
"28562041230c6d575e233e4ed1b35c514884d964": {
"balance": "100000000000000000000000000"
},
"16eb6896a5a83d39ac762d79d21f825f5f980d12": {
"balance": "100000000000000000000000000"
},
"f09e3f1de27dd03a1ac0a021b2d9e45bde1b360c": {
"balance": "100000000000000000000000000"
},
"2d87547819c6433f208ee3096161cdb2835a2333": {
"balance": "100000000000000000000000000"
}
}
}

View File

@@ -181,8 +181,8 @@
"stateRoot": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544"
},
"hardcodedSync": {
"header": "f90215a0ea51746efaaede944c3397e41ae72b7908c8ce25967c1edcd02618b068486feba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794829bd824b016326a401d083b33d092293333a830a0aee38c1032f191c3d42cc581f53d31adb1f0d91f463e6a8c12fc35fd1db58d5aa0568149713d45e959d5d07624917617d0d7865124c25c28eb9b798013096ddeafa0847bb20a0b62d1d8e2b467c33b28ded6796c556cd2b2a169b640b40e58fd2340b9010048c03883204a1ef0204300012248c8841814900c04362858000450c8927a22a88d5b471c4869c00001d8641080695910c20801022c2910408829a8002620115dc8200ec2851300611284301c3243e091030706068c8160505403250d03f44437410080072a69048082b43070805d08424a021328221500101418463040904ca094a189c801e50000c41402603426c4701a6302e1023040080d8380e21d600a2083003a2604082001b183068d1470840a49008a514148800a08030a8002c821b24010f20ea31c55060582801c14483ec29d4081c7152d2244840016c123da6f42249b6002c8401618a0000a8c8df892954d8080800c160244453086480d8264b6870ae8321581e6cb836ed001837a30a08379e5a2845c72b9c0947070796520e4b883e5bda9e7a59ee4bb99e9b1bca06883c088b374f7c667ed0fda0f1ec7c18890c892b88f14b41f03e7d927bcca82880db92c004f0313a8",
"totalDifficulty": "9242028122621986440675",
"header": "f90212a0113ba3b1153987fc483b01ccfe9ecadbdc36a7b264be75d6486cb6b694cc38a1a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479452bc44d5378309ee2abf1539bf71de1b7d7be3b5a0d91db5900e312a1ba8d39505406a95dc0ea20393b723c4bf488ade4e3c4ee4c3a05e63ab076852043b1c2fe010e2f14ab13dcc8e1c546ac497a24ce88c4abf3056a0b72e4a776f895459b6bf0937040990d868b1f45889aeaa26684e07472263fc31b90100b00200000063664554889124822ce2001022840543085d5810042382888542ca3816801780384384cd6851081cdc4d4b2b205a814b049198110a6869d60f4009a79c3854c9000581044889080000611c09142200106552000044027024004038092102814ed6c48040a8715851088a20108e80165f8c0c514019037a0000121304b2343416800b029000024404248238a06818414cb8690244879491855405026bc8250220520992c2380099d10024411c6048424083d1307822442d8444700405147883c4c041300aaa2408bb61084012983825a22830040a180106b5e27182088060b111515832902903a8f1d432a48004d0250437106a503491000048a91587067a897789f4d78371d801837a309c8379ffd7845c9d879e9150505945206e616e6f706f6f6c2e6f7267a0db22736cb3f06f9c86804902731fa6841eaaa1cd6326ea2a30e9c304d48bdd04880323b06837344cb8",
"totalDifficulty": "9633968582330911261986",
"CHTs": [
"0x0eb474b7721727204978e92e27d31cddff56471911e424a4c8271c35f9c982cc",
"0xe10e94515fb5ffb7ffa9bf50db4a959b3f50c2ff75e0b8bd5f5e038749e52a11",
@@ -3729,7 +3729,104 @@
"0x8ed199e2fd654bfc9dfd5e7ea7dc82bea9f4535eb480c95984a5a6bc1533bf8e",
"0x4e5475dae57c548460d4ddd15583223bf2a4a2046c2ee56ca670892794a37d90",
"0x80409971b3e59ec71deb1a158a92ab6fe8318cb9adebcf583586e23e42d370c4",
"0xeb35d7c78965874110f67b77307deae4bb29dc98c01fbac3737409ede61df7c6"
"0xeb35d7c78965874110f67b77307deae4bb29dc98c01fbac3737409ede61df7c6",
"0xd358b672db99b007ac54ef3ea7c77c0eb0b4e9cc1437ca4eb70d71aaaf84b6f2",
"0x0ca4c79c1709b947794ae73dd3b73b357273c4e5cfc83ec85c4c2b649e10740f",
"0x704635b2335b5ad2be0e586e60770dc1e0548794ee2c1670cbfbc2ed0c1f64ae",
"0x6a6f2425c865216b49e7e73026fd2e9cc02f131c0050ce849f274c37828909f0",
"0xce31e62ac098db0fef0823941009b826d4e5b8e11f2e01208ee6abccb160c0cc",
"0x5669c0e6ccaa8abff08e944fe8bdcf0001dce9c10ef8b90d7f821819e028dcb6",
"0x37b59281d4eec501ed45d68c2bfac450d336ee5a18ecb7d2d812763d2cfd4321",
"0xfb52f084a5ffd63001f47acdb2ea62e91714af63f896c151100350d83bd2c7e4",
"0x67bfc4a94fde6e81b54ebe52914c0d73a053bbac22d6d64862e987e53c78ed61",
"0x49c141a8ac1124f40d06c569f49363a8af092d0028b02d8f4c895af2f86d0f28",
"0x5c81c85021692d5dd1bdbd3a4543ec86d49e674380a0e5f59d4400902d7e753b",
"0x9b46d19b0cee63461453a487bbf855fb4a7d70933ce2b7445d1dce8dbbc11cf9",
"0x50fe5cb0ddf34ed2ee8341848bc00df89fda05fbf0ebb1b34d12afe9e5ae4d1a",
"0xd56b4c4880798175c2db50c5c5d6845b5c1e7b6b33172ba107f5de075ed09def",
"0xe0928a4092e5ab5b9a34a8748c3ddf86a6a9ab50e85777c4e1e8088ac7b44ae7",
"0xfcde6d53ff8286afecafa27d608e94c07a4d78813edeccb73a1076772d1f7e83",
"0x1bff0dc76b0d8877a9ea133a023a5dc0f88559f16f0adffbf7b4d58b6be487a1",
"0x5252a71f6c9784b538ecd810bded0520f349f5aa748657a9b4422474eee08388",
"0xc4cccd5ae51babfe8e9f76af2c64227b0fd63bc2f4336b7820a32846516d9835",
"0xd07bc360f06a492a13047247448ba37fc9a167bd81ee63607976be269d245e14",
"0x9499022a6b509dd05eae2a7c799c332382b810843065e82ec72891b771cc3a8a",
"0x0ba258fb2666908035e53ec37a96ee13719779de43f14a57223b704961ef667a",
"0x4dec79cac5e3b414aa835c69bb2c580ccc03eaed675b61070f37b606ff4715bd",
"0xac640ffa67870bd91b1ff36450256fb1e5f59e65f4ef844875185c38f7f986b5",
"0x0af93eccdfbb75dc353ff31949329b3c96ffa93f63e9ae4a515f6e177e201d35",
"0x5a2d5ba9defce6db1bff0bbbe4eee170fe3b9c0ecb4a1ec6e16f904b55c07beb",
"0xd92f1c26de95255b1e0926341c35b5bfd106820dbdcb381400516d247062f3fd",
"0x447ec0cf1a32e8201cb92d0ad13adc6e664a07612bf38ce9c598c799cd947fb1",
"0x28460192df35aec41fe3992efc94da904d69e4b65e518fd2c530b38c1ec88819",
"0x6b0557132b0efe568a96f77fad4f1e18cf05670c007488052f347cf3461ee98c",
"0xb82f3f400a0edc100ddd6e82c2ea587eb5d56ea0f8faa379f8fa259f31ea0838",
"0x370b650e0bd14d9e5d749f628fca91ff47184473b6cba948e9ad3492a68bed5e",
"0x794e423feca451babc044923a79ceab62ff3a9a7e8947dcadd0d91f78a11cff6",
"0x7fe410432bfc7048e6685eb6bf0b4ae9808864a2e09ed1d373dc211f40c59da7",
"0x9f53d260f145de7b48c04829abd97989bc11d748af7d119ebf56948ca438913a",
"0xad5ad5cd5ff452e16c07bba12f0b34bb1c3c8c33d54db45b515cf6761d6a1cc8",
"0xcc6e322ea2c52af09d720524c85629019eac5ca01dcec5da887ad4b32157b9e4",
"0x5d3ddb9fa275898453e8430b26270e2812709717898683f0a3291291b29d688a",
"0xeff621bef47694a862a320a661b691b491e4a5c44e1d2026c9756f84903a6375",
"0x110e7059d20e4531323dcf981ad6cb9d67d56815c54394ab1b0b7af4235aa218",
"0xe44d27931b9429204cd2e9cba838f0ed707d5668ab55ecf2c906b2748fa1f16d",
"0x9d7166683764cde8445c58697df637cd48e35b3ad00f6e6d4bbf12844ba217c5",
"0xf5f6625754100a91cd7283d47e72cca73c39e5fa2e0405d427430bccd49cc2bb",
"0xd6b27ee81a557ff5d8947225c19f3ba023af18415a413acdf438548b24902427",
"0xccc665895dbabf0d8775c5fddf167b41579b0e6bff8fe99c8da00622334c8861",
"0x1986e5fd526af0a0e74ab83cb82c18dbd5a73fe72b94c8ca10318f8f6bd2d98a",
"0xd3f245d6f37b0c47506fc4a2b12d85ff87eb35c2f45f82c3e5bebdc7362d8cd6",
"0x53b97494c77ef9a843ce61b2a58231bc145b492b710fc3dcf79c297187993bbf",
"0x00d4cd1f9460a8625ed0a539257e58a9ab8051ff239172f0a9437cb9f0d1a11f",
"0x1c3d92f1e67b04c24db2eb04184ca7ccd5533540aca4dcbe084a70648c347ee5",
"0x200e39cb704bcda42f547c0cae54c0dd4c0b1aaf17469d69deaa67d3ef0d95c5",
"0x5aa208366dc50c2e9f0075b0e8aad396851f54a42c9ec1114c2994da0c2fcace",
"0xbea70811c324fb1553c4fc492521ce062756da0a469d8f98cd6c0f7a3a7b5e3a",
"0x79aa191ef9975049a5f2b8b7e2921a3f78d045b99b7a569a93680c5ee2600a18",
"0x233fd477509141aed423948a0c5c5b8f0ab8cc3c4836c0f44c8cd6c0811b419c",
"0x1737e144530678804416cd7c3c8200f54f395bf7712c9ade8340988e1e123af5",
"0xbdad2ae32cbfc13446adfe9e4101f32fb52b1e336c165a1125c917d6c1a1fceb",
"0xc20dedeedd63be4c10d92d9d0e7b47e20d503f331cb31d47ec9e99b915305ba0",
"0x262281f50e2892d8cfca3b8f8a6645b5931fb4601755f02fb863d719cd690381",
"0xb0a717f11ff1e3f1a4bd775792c7e5a75af6e56967ab1615be6b4941ca9315e3",
"0xe8f45b1aee0fb0e87148b316ee0ce662ae3bb2abd05e9666429fcf30893641b1",
"0xe7a439e2577c4f892921f798efa19353d236146b849c20253b07f03194b36286",
"0xf4eda704d4864d8fccefecc246fb683dbdeee5468a53dd11d71d71477d170422",
"0x308d977f739b7a8cb4810242fb447a8f6cad45389a127f5822ca2df48fa9df86",
"0x3115d6d0f174e00bf3e5704f57e44b62f7e279894ce62f39568ffe4367fc5a44",
"0x6b6e6354b8d1e1ab0430fe2a5068b2b2263ff453676dbfdce5da60a6d625f20f",
"0x9b8a7b122572f459d946e67a1c78973040bcf67a64327f689d4016c53afcc4cf",
"0xa367c0bc2e6029afec518db94fa79288801f5ebf2cba50980fc9754a40784d19",
"0xc1a017142eac944b5fda4cd66a9b6b6dc64551c3ce958e8811797433b96ec5d8",
"0xc9e3999a3f162d42ae52644ce4f765b5ccc7fe2a4c91cc59048eeb8c8086718e",
"0x67c135523c9703aa1f1b653d9279804af4cd81cd3de99e10a853b42d78143914",
"0x9af2390bb01b245c65f76454f1c80102871131417cc8fbff4b1ada056d04dd47",
"0xf4cec7d4f4a76c769021ab0dab848d668fd36e910259e45094d88defabd13448",
"0xe2a224fd4510ac5f8a6782d2eed14ee164e6bb92d3f0a7e5e71497046fe9f30c",
"0x9884ca2b5533c36e03fecf28470fd3c45292dc623fb220c5eb0a580781fbe724",
"0x078b1365c5dc77fdea6bb010fab6c4dede06e27386d4d5f205bf7e7857b03865",
"0x8f930fa645409fc1d7fb28637360489a5e5eaa6554857441c3fd8990243d9972",
"0x2e21ac485ed90007e8b69cf247c28b25361729bcc7501a3296f9c06dd0742888",
"0x46c3ea9e86ad55d87b6f5d50fd9c145bcb6ca90a4d570c1f86b5532b0762d8c0",
"0x87edc87f5ac353d64b0f157ce3e3180ce73fdd1f0ae9db1406e49581f1780de7",
"0xc940108991c82f871c3eea33ec93951c9bc33cd0aba1c77262cb6fc6ea16f4eb",
"0xba2f1d37cebd9bcde635bee4c0f260af8fddb43a84508f244b562dd1f7bdbe92",
"0x738e8d02870cf37ba27db2eb621d5f7b32a225010de41e3983ed389ebaa0e364",
"0x84af8e6e7ceb53e068bdf16091bfe966458bb5d3e4a925360411a213aaf46a5c",
"0x548302ac8a0af1ef5bb91d469f66f8669cdb2a07c432e7504a806e00487adb63",
"0x35bc3a284170d090e6fe053d3bd2a8fc3aa299d113b69b90340ca4c7e019016d",
"0xfe7b61c4388f2615642f9ffb44279f31a98c0f0d2f3f37b5f77ba09a67c12737",
"0x864581a4e526055847c252f6169bc54b5a1615de8e1cb7e80c649315b04a9aab",
"0xb8b4c67301cf9d3e91ae59a0394c8085737358bde297c58688b48a9d33c04205",
"0xa1ee0d1c7d50d37f96505ed06b166722f47fdd784b71bb3d47539ae40be96262",
"0x63b2658609397ec6a9e9d9d0a5b318b79b1e39348606ca53e0f84f6466d3aad4",
"0x2211abc4f8bbd6784aa191805465b10520a6c505d6257063aa9b911d5781fb89",
"0xefed35d1327328deece22922f08d3c3931c80c1ea9a8bc719b8226f38823bb6d",
"0x64b862e2d5a6c24d569f3352b8524ebfecfd5a3205a3200ec78df72d79a66838",
"0x6da8edf169a9c78307258a723c1ac1d96db20a7131018efad16f0606683c0f07",
"0xbae1427beab8c3e71cea57e5f9cdd55bc278c6d6073ae2628f0d3efbf9894a42",
"0x389bbd1b3fa390e8d3339cf5b018ec64d9cfc02bbcb801acad0857fe377ed83b"
]
},
"nodes": [

View File

@@ -0,0 +1,917 @@
{
"name": "Görli Testnet",
"dataDir": "goerli",
"engine": {
"clique": {
"params": {
"period": 15,
"epoch": 30000
}
}
},
"params": {
"accountStartNonce": "0x0",
"chainID": "0x5",
"eip140Transition": "0x0",
"eip145Transition": "0x0",
"eip150Transition": "0x0",
"eip155Transition": "0x0",
"eip160Transition": "0x0",
"eip161abcTransition": "0x0",
"eip161dTransition": "0x0",
"eip211Transition": "0x0",
"eip214Transition": "0x0",
"eip658Transition": "0x0",
"eip1014Transition": "0x0",
"eip1052Transition": "0x0",
"eip1283Transition": "0x0",
"eip1283DisableTransition": "0x0",
"gasLimitBoundDivisor": "0x400",
"maxCodeSize": "0x6000",
"maxCodeSizeTransition": "0x0",
"maximumExtraDataSize": "0xffff",
"minGasLimit": "0x1388",
"networkID": "0x5"
},
"genesis": {
"author": "0x0000000000000000000000000000000000000000",
"difficulty": "0x1",
"extraData": "0x22466c6578692069732061207468696e6722202d204166726900000000000000e0a2bd4258d2768837baa26a28fe71dc079f84c70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0xa00000",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"seal": {
"ethereum": {
"nonce": "0x0000000000000000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
},
"timestamp": "0x5c51a607"
},
"nodes": [
"enode://06333009fc9ef3c9e174768e495722a7f98fe7afd4660542e983005f85e556028410fd03278944f44cfe5437b1750b5e6bd1738f700fe7da3626d52010d2954c@51.141.15.254:30303",
"enode://176b9417f511d05b6b2cf3e34b756cf0a7096b3094572a8f6ef4cdcb9d1f9d00683bf0f83347eebdf3b81c3521c2332086d9592802230bf528eaf606a1d9677b@13.93.54.137:30303",
"enode://573b6607cd59f241e30e4c4943fd50e99e2b6f42f9bd5ca111659d309c06741247f4f1e93843ad3e8c8c18b6e2d94c161b7ef67479b3938780a97134b618b5ce@52.56.136.200:30303",
"enode://67913271d14f445689e8310270c304d42f268428f2de7a4ac0275bea97690e021df6f549f462503ff4c7a81d9dd27288867bbfa2271477d0911378b8944fae55@157.230.239.163:30303",
"enode://a87685902a0622e9cf18c68e73a0ea45156ec53e857ef049b185a9db2296ca04d776417bf1901c0b4eacb5b26271d8694e88e3f17c20d49eb77e1a41ab26b5b3@51.141.78.53:30303",
"enode://ae8658da8d255d1992c3ec6e62e11d6e1c5899aa1566504bc1ff96a0c9c8bd44838372be643342553817f5cc7d78f1c83a8093dee13d77b3b0a583c050c81940@18.232.185.151:30303",
"enode://ae8658da8d255d1992c3ec6e62e11d6e1c5899aa1566504bc1ff96a0c9c8bd44838372be643342553817f5cc7d78f1c83a8093dee13d77b3b0a583c050c81940@18.232.185.151:30303",
"enode://b477ca6d507a3f57070783eb62ba838847635f8b1a0cbffb8b7f8173f5894cf550f0225a5c279341e2d862a606e778b57180a4f1db3db78c51eadcfa4fdc6963@40.68.240.160:30303"
],
"accounts": {
"0x0000000000000000000000000000000000000000": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000001": {
"balance": "0x1",
"builtin": {
"name": "ecrecover",
"pricing": {
"linear": {
"base": 3000,
"word": 0
}
}
}
},
"0x0000000000000000000000000000000000000002": {
"balance": "0x1",
"builtin": {
"name": "sha256",
"pricing": {
"linear": {
"base": 60,
"word": 12
}
}
}
},
"0x0000000000000000000000000000000000000003": {
"balance": "0x1",
"builtin": {
"name": "ripemd160",
"pricing": {
"linear": {
"base": 600,
"word": 120
}
}
}
},
"0x0000000000000000000000000000000000000004": {
"balance": "0x1",
"builtin": {
"name": "identity",
"pricing": {
"linear": {
"base": 15,
"word": 3
}
}
}
},
"0x0000000000000000000000000000000000000005": {
"balance": "0x1",
"builtin": {
"name": "modexp",
"activate_at": "0x0",
"pricing": {
"modexp": {
"divisor": 20
}
}
}
},
"0x0000000000000000000000000000000000000006": {
"balance": "0x1",
"builtin": {
"name": "alt_bn128_add",
"activate_at": "0x0",
"pricing": {
"linear": {
"base": 500,
"word": 0
}
}
}
},
"0x0000000000000000000000000000000000000007": {
"balance": "0x1",
"builtin": {
"name": "alt_bn128_mul",
"activate_at": "0x0",
"pricing": {
"linear": {
"base": 40000,
"word": 0
}
}
}
},
"0x0000000000000000000000000000000000000008": {
"balance": "0x1",
"builtin": {
"name": "alt_bn128_pairing",
"activate_at": "0x0",
"pricing": {
"alt_bn128_pairing": {
"base": 100000,
"pair": 80000
}
}
}
},
"0x0000000000000000000000000000000000000009": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000000a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000000b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000000c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000000d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000000e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000000f": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000010": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000011": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000012": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000013": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000014": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000015": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000016": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000017": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000018": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000019": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000001a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000001b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000001c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000001d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000001e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000001f": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000020": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000021": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000022": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000023": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000024": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000025": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000026": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000027": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000028": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000029": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000002a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000002b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000002c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000002d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000002e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000002f": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000030": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000031": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000032": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000033": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000034": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000035": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000036": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000037": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000038": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000039": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000003a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000003b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000003c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000003d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000003e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000003f": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000040": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000041": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000042": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000043": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000044": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000045": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000046": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000047": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000048": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000049": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000004a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000004b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000004c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000004d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000004e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000004f": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000050": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000051": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000052": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000053": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000054": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000055": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000056": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000057": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000058": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000059": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000005a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000005b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000005c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000005d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000005e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000005f": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000060": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000061": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000062": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000063": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000064": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000065": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000066": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000067": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000068": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000069": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000006a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000006b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000006c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000006d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000006e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000006f": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000070": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000071": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000072": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000073": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000074": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000075": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000076": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000077": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000078": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000079": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000007a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000007b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000007c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000007d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000007e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000007f": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000080": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000081": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000082": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000083": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000084": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000085": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000086": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000087": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000088": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000089": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000008a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000008b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000008c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000008d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000008e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000008f": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000090": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000091": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000092": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000093": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000094": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000095": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000096": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000097": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000098": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000099": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000009a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000009b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000009c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000009d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000009e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000009f": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a0": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a1": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a2": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a3": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a4": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a5": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a6": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a7": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a8": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a9": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000aa": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ab": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ac": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ad": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ae": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000af": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b0": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b1": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b2": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b3": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b4": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b5": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b6": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b7": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b8": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b9": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ba": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000bb": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000bc": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000bd": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000be": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000bf": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c0": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c1": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c2": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c3": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c4": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c5": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c6": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c7": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c8": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c9": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ca": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000cb": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000cc": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000cd": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ce": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000cf": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d0": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d1": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d2": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d3": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d4": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d5": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d6": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d7": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d8": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d9": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000da": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000db": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000dc": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000dd": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000de": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000df": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e0": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e1": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e2": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e3": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e4": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e5": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e6": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e7": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e8": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e9": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ea": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000eb": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ec": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ed": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ee": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ef": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f0": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f1": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f2": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f3": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f4": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f5": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f6": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f7": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f8": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f9": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000fa": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000fb": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000fc": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000fd": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000fe": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ff": {
"balance": "0x1"
},
"0x4c2ae482593505f0163cdefc073e81c63cda4107": {
"balance": "0x152d02c7e14af6800000"
},
"0xa8e8f14732658e4b51e8711931053a8a69baf2b1": {
"balance": "0x152d02c7e14af6800000"
},
"0xd9a5179f091d85051d3c982785efd1455cec8699": {
"balance": "0x84595161401484a000000"
},
"0xe0a2bd4258d2768837baa26a28fe71dc079f84c7": {
"balance": "0x4a47e3c12448f4ad000000"
}
}
}

View File

@@ -0,0 +1,902 @@
{
"name": "Kotti Testnet",
"dataDir": "kotti",
"engine": {
"clique": {
"params": {
"period": 15,
"epoch": 30000
}
}
},
"params": {
"accountStartNonce": "0x0",
"chainID": "0x6",
"eip140Transition": "0xaef49",
"eip150Transition": "0x0",
"eip155Transition": "0x0",
"eip160Transition": "0x0",
"eip161abcTransition": "0xaef49",
"eip161dTransition": "0xaef49",
"eip211Transition": "0xaef49",
"eip214Transition": "0xaef49",
"eip658Transition": "0xaef49",
"gasLimitBoundDivisor": "0x400",
"maxCodeSize": "0x6000",
"maxCodeSizeTransition": "0xaef49",
"maximumExtraDataSize": "0xffff",
"minGasLimit": "0x1388",
"networkID": "0x6"
},
"genesis": {
"author": "0x0000000000000000000000000000000000000000",
"difficulty": "0x1",
"extraData": "0x000000000000000000000000000000000000000000000000000000000000000025b7955e43adf9c2a01a9475908702cce67f302a6aaf8cba3c9255a2b863415d4db7bae4f4bbca020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0xa00000",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"seal": {
"ethereum": {
"nonce": "0x0000000000000000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
},
"timestamp": "0x5c2d2287"
},
"nodes": [
"enode://06333009fc9ef3c9e174768e495722a7f98fe7afd4660542e983005f85e556028410fd03278944f44cfe5437b1750b5e6bd1738f700fe7da3626d52010d2954c@51.141.15.254:30303",
"enode://93c94e999be5dd854c5d82a7cf5c14822973b5d9badb56ad4974586ec4d4f1995c815af795c20bb6e0a6226d3ee55808435c4dc89baf94ee581141b064d19dfc@80.187.116.161:25720",
"enode://ae8658da8d255d1992c3ec6e62e11d6e1c5899aa1566504bc1ff96a0c9c8bd44838372be643342553817f5cc7d78f1c83a8093dee13d77b3b0a583c050c81940@18.232.185.151:30303",
"enode://b477ca6d507a3f57070783eb62ba838847635f8b1a0cbffb8b7f8173f5894cf550f0225a5c279341e2d862a606e778b57180a4f1db3db78c51eadcfa4fdc6963@40.68.240.160:30303"
],
"accounts": {
"0x0000000000000000000000000000000000000000": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000001": {
"balance": "0x1",
"builtin": {
"name": "ecrecover",
"pricing": {
"linear": {
"base": 3000,
"word": 0
}
}
}
},
"0x0000000000000000000000000000000000000002": {
"balance": "0x1",
"builtin": {
"name": "sha256",
"pricing": {
"linear": {
"base": 60,
"word": 12
}
}
}
},
"0x0000000000000000000000000000000000000003": {
"balance": "0x1",
"builtin": {
"name": "ripemd160",
"pricing": {
"linear": {
"base": 600,
"word": 120
}
}
}
},
"0x0000000000000000000000000000000000000004": {
"balance": "0x1",
"builtin": {
"name": "identity",
"pricing": {
"linear": {
"base": 15,
"word": 3
}
}
}
},
"0x0000000000000000000000000000000000000005": {
"balance": "0x1",
"builtin": {
"name": "modexp",
"activate_at": "0xaef49",
"pricing": {
"modexp": {
"divisor": 20
}
}
}
},
"0x0000000000000000000000000000000000000006": {
"balance": "0x1",
"builtin": {
"name": "alt_bn128_add",
"activate_at": "0xaef49",
"pricing": {
"linear": {
"base": 500,
"word": 0
}
}
}
},
"0x0000000000000000000000000000000000000007": {
"balance": "0x1",
"builtin": {
"name": "alt_bn128_mul",
"activate_at": "0xaef49",
"pricing": {
"linear": {
"base": 40000,
"word": 0
}
}
}
},
"0x0000000000000000000000000000000000000008": {
"balance": "0x1",
"builtin": {
"name": "alt_bn128_pairing",
"activate_at": "0xaef49",
"pricing": {
"alt_bn128_pairing": {
"base": 100000,
"pair": 80000
}
}
}
},
"0x0000000000000000000000000000000000000009": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000000a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000000b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000000c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000000d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000000e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000000f": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000010": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000011": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000012": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000013": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000014": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000015": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000016": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000017": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000018": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000019": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000001a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000001b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000001c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000001d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000001e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000001f": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000020": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000021": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000022": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000023": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000024": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000025": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000026": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000027": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000028": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000029": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000002a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000002b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000002c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000002d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000002e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000002f": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000030": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000031": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000032": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000033": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000034": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000035": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000036": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000037": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000038": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000039": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000003a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000003b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000003c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000003d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000003e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000003f": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000040": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000041": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000042": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000043": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000044": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000045": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000046": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000047": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000048": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000049": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000004a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000004b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000004c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000004d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000004e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000004f": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000050": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000051": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000052": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000053": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000054": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000055": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000056": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000057": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000058": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000059": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000005a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000005b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000005c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000005d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000005e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000005f": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000060": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000061": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000062": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000063": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000064": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000065": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000066": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000067": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000068": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000069": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000006a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000006b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000006c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000006d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000006e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000006f": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000070": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000071": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000072": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000073": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000074": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000075": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000076": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000077": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000078": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000079": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000007a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000007b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000007c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000007d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000007e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000007f": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000080": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000081": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000082": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000083": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000084": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000085": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000086": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000087": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000088": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000089": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000008a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000008b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000008c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000008d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000008e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000008f": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000090": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000091": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000092": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000093": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000094": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000095": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000096": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000097": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000098": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000099": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000009a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000009b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000009c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000009d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000009e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000009f": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a0": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a1": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a2": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a3": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a4": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a5": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a6": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a7": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a8": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a9": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000aa": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ab": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ac": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ad": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ae": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000af": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b0": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b1": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b2": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b3": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b4": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b5": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b6": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b7": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b8": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b9": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ba": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000bb": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000bc": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000bd": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000be": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000bf": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c0": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c1": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c2": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c3": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c4": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c5": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c6": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c7": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c8": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c9": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ca": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000cb": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000cc": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000cd": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ce": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000cf": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d0": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d1": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d2": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d3": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d4": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d5": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d6": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d7": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d8": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d9": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000da": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000db": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000dc": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000dd": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000de": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000df": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e0": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e1": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e2": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e3": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e4": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e5": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e6": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e7": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e8": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e9": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ea": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000eb": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ec": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ed": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ee": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ef": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f0": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f1": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f2": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f3": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f4": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f5": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f6": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f7": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f8": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f9": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000fa": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000fb": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000fc": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000fd": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000fe": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ff": {
"balance": "0x1"
},
"0x25b7955e43adf9c2a01a9475908702cce67f302a": {
"balance": "0x84595161401484a000000"
},
"0x6aaf8cba3c9255a2b863415d4db7bae4f4bbca02": {
"balance": "0x4a723dc6b40b8a9a000000"
}
}
}

View File

@@ -7,17 +7,31 @@
"stepDuration": "0x4",
"blockReward": "0x4563918244F40000",
"validators": {
"list": [
"0x00D6Cc1BA9cf89BD2e58009741f4F7325BAdc0ED",
"0x00427feae2419c15b89d1c21af10d1b6650a4d3d",
"0x4Ed9B08e6354C70fE6F8CB0411b0d3246b424d6c",
"0x0020ee4Be0e2027d76603cB751eE069519bA81A1",
"0x0010f94b296a852aaac52ea6c5ac72e03afd032d",
"0x007733a1FE69CF3f2CF989F81C7b4cAc1693387A",
"0x00E6d2b931F55a3f1701c7389d592a7778897879",
"0x00e4a10650e5a6D6001C38ff8E64F97016a1645c",
"0x00a0a24b9f0e5ec7aa4c7389b8302fd0123194de"
]
"multi": {
"0": {
"list": [
"0x00D6Cc1BA9cf89BD2e58009741f4F7325BAdc0ED",
"0x00427feae2419c15b89d1c21af10d1b6650a4d3d",
"0x4Ed9B08e6354C70fE6F8CB0411b0d3246b424d6c",
"0x0020ee4Be0e2027d76603cB751eE069519bA81A1",
"0x0010f94b296a852aaac52ea6c5ac72e03afd032d",
"0x007733a1FE69CF3f2CF989F81C7b4cAc1693387A",
"0x00E6d2b931F55a3f1701c7389d592a7778897879",
"0x00e4a10650e5a6D6001C38ff8E64F97016a1645c",
"0x00a0a24b9f0e5ec7aa4c7389b8302fd0123194de"
]
},
"10960440": {
"list": [
"0x00D6Cc1BA9cf89BD2e58009741f4F7325BAdc0ED",
"0x0010f94b296a852aaac52ea6c5ac72e03afd032d",
"0x00a0a24b9f0e5ec7aa4c7389b8302fd0123194de"
]
},
"10960500": {
"safeContract": "0xaE71807C1B0a093cB1547b682DC78316D945c9B8"
}
}
},
"validateScoreTransition": "0x41a3c4",
"validateStepTransition": "0x16e360",
@@ -64,8 +78,8 @@
"gasLimit": "0x5B8D80"
},
"hardcodedSync": {
"header": "f90247a03dc1f4ed47c057717131ce81535d06194d990be6969334e9b8034e0c875f9dffa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940010f94b296a852aaac52ea6c5ac72e03afd032da0fd1833e970c207ca16e1e74d937c9d8e01a1f719643fb25963028427295fc2cca00d9d5e376ebe3558b412402702d34a93256bb03a61df9f17ae234f0a70f95b20a0129c38f28acd251820f96305d217511a725a1fae1a434d77034bd7efef1f9f5ab901000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000080000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffa839f3801837a1200834bb5f3845c7361249fde8302020a8f5061726974792d457468657265756d86312e33322e30826c6984171cd849b841d077cf579661ac8634ee865b5cc67918223aed686d6ba189624a6f6c0dfc5249418b25423e30e072a79d5377e01845d5234ff5e0b9b0207b1bf2515f805b47e300",
"totalDifficulty": "3500253997070921577369506418666760871805116639",
"header": "f90247a0d0c0f490e8e5045fa96fd77ce45ed983900feaab964b2b0ba3a2d3a6b5e0f842a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479400d6cc1ba9cf89bd2e58009741f4f7325badc0eda0c91e59c81193c4fead4f64ecaa349e97056409dfbb787772ea3c1e55e7582b2ea08be1332f5e7eac286c7e5e5ccf3760e47f4a919548c15e748ad4351bb8405f9aa054e0533aa3433f4d07afa226230c867fc1e2844b5f49b25aba8df17630d9f8c8b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffe83a26801837a12008306f78d845c9da0b09fde830203088f5061726974792d457468657265756d86312e33332e30827769841727682cb841d6db93a25c84287603ee26e48db0dd301753840cc7283d411d3febd0485e02b2520086bebfb3aec1ab69403f45f0d59249bf0d458f33aa268dc4badefc73c8d300",
"totalDifficulty": "3571337622391237938633151520660827524104528124",
"CHTs": [
"0xdb9557458495268ddd69409fc1f66631ed5ff9bf6c479be6eabe5d83a460acac",
"0xd413800c22172be6e0b7a36348c90098955991f119ddad32c5b928e8db4deb02",
@@ -5161,7 +5175,109 @@
"0x7ba1756f8fa6637d8cb6cc588a679f6366827bc2044865744837c63e8a5aadcc",
"0xfc1a94a88f1e52bb78a0862eea4b996444f0264a3b301c1a31e59744d0216de8",
"0x79472bc4de84a0c430f15bcf8569486cddd2de985409ceb8e48abec8aa3e3fe7",
"0x02bc578dcc715304c651a43d8dcb4a761d2073a93cca2c39da3ee513f0c6d415"
"0x02bc578dcc715304c651a43d8dcb4a761d2073a93cca2c39da3ee513f0c6d415",
"0xcf6175cfa60c20178241c18111d64f8837ec008751c5c333bee96c616d3cb6d1",
"0xd8281202c7b6da2a2541cd7f8d4270066f6546bec601e83647896ebdf0f2eb66",
"0xc4975ca8b2b71f61d2ba2825833df91096bd733301d54a3c7b6eca016ac14153",
"0xd01d6f14e93c8ba17a602378bce1c9bdb51373675109d6233c497b6c638a03a0",
"0x805057e19b7dd857ec014b4e6333bb60f48c02d29b128fe37a69f952df8ef16b",
"0x69c55bdbaf74bfa3d53ed32b79dd35ac2c24dd723a1c0bfd70871cefa4dbb8a8",
"0x523efe8059e6e8e2abd85d77d22123f97cbbd9864b4a3ac1fe0c0e4b8a7131eb",
"0xe5a4f129016bcfbd71913d1eff01cec924f9d130b8762c921d43fe5bbbbdbbd0",
"0x07f68773d16907348ac6e7c5be293ee1163ef41b91a2a8abb17a004c4796fb42",
"0x90742f88c71f9e689b6d2ca0236c48bba0e8ddeace5fa4d53a5af082055cfd73",
"0xaf7af6e9f695c4ca9e9a3c0229d94cbf02fcafbc4ed978a6b662862182308a72",
"0x0208eac99df5025cab13d9767a2ba3e42ba1eccb72cfa01d87e834d15eea3751",
"0xee9ff9384cef76b51a9d5b8eb12fd7e00ee7f8142f81bd68393e7fcf0eaef90a",
"0x4770986e657683d901d73df444836f11f169f94ac55ec81e4e19f2212052788c",
"0x9f9c16d009da6e8ee20d9d5f3bd7f1a77b853dfd19beef68d980fca6bce2b707",
"0x468efd7c8dad29cfff0e278fd950f89e2d5a57d6824c6c1a7a7659bd7e7c0ffe",
"0xd0391bd0a2c1fb2260d89bd5e519d4ef26b4945a7ad0c1b695687fe1b24698dd",
"0xdef9ee668e09f8769b2c706a8de426e06f0bd9c264e67bf0c0bb177b851cef23",
"0x10c5b79048e611c6e65f92dd54754753e595cd8f8f0f1005d7a647fa59deeb78",
"0x4ce6d5812d2565237a9b018ed6ec386cf3e9fe1f2f429605288f2ef744c5a940",
"0xbbacf6662d816d5eb14fc1271c1a3404de94e12c175545bc8273c231c280b789",
"0xb216fd154d3726f16907ae571728d92ae2199872f180e4cd6be3b53a8dd43ae0",
"0x2b76e6685604c69f29399451c66ce053ae033ab011eb52c97c112df968e37232",
"0xf93b8076ce0dc6742196d2c9af501fad39f570cd927e8fe3b8dac4127a20a6a4",
"0x35027cc654f998af75b8379fac0a9d51703f058b518880e25e658151619f1611",
"0x3e7f59319228d40e5e07c06b696ad6478237ed0c8a71cff418ac259c6b5579e4",
"0x7295e21fccabab1545c1e64a57f0401e62689057ab4fef26f70c8d02b63867ab",
"0xb06bcf07fe1345c41ba16df213d699e2e185ef2fd3b5e19b194459d0b7baffc1",
"0x1b13d005a29e35fff33373e2d8abc81805a85e7970b48dca8fd605069c8a0d85",
"0x90a5a61ce554bb73253d7f62c78b1764f03fb0fd8f65b6aae4f9e529acb1d991",
"0x1b1eccf7565339748947358caf473ba0cea743da2ed4790763d3ac8c402f261c",
"0xef9b05ae7ce93febce342336e40922e0884891da43aac06f3e9bbfc0aec688f9",
"0x11e1075b50de92e960d0d65e9b37b3cec81095f5afc2afccc6a9a8a325264049",
"0x128e6dba4205701f673dda9e980dc0c02f3c0c8cbc570f9a240257a261f81b39",
"0x6fd9d3eaffaeebd52ce93ac8fcd0f69b146e2c0b05218850de1c9218db8ecd8f",
"0xc47e3487ad63b7db773f413cd5302818061f168409c27ff2daba4579c0a4263f",
"0x0a55695d4a132063735f7319d3a90a2e0b83fd6ec6b6f9994068f928f68afe12",
"0x39403d84aa319edbb18e0313a61ae075ba9c5dae40b9850eccbfc3e09e6b27a7",
"0x79ba98eede4cd0b7031472baacab20df85c704a26e4cfaa6e01e3d4a9d26ca39",
"0x219240759d36a317f269e4301256164cb3709628e0ba07e90a6bedd664cea059",
"0xec793562f8498937f270c6ae5490ab8f2ad21a20510699dc4d7d4d0139efeb3b",
"0x0a3e9c209903b906013c8876cb4292e6ccc8b76dbf4af2ca25d8260f9f8e7c22",
"0x0eb347bb16d897b4909dcaf31a0009e198cd197f722075c112fe29bc9f017f20",
"0xac1e6a97c51f5051dc8f3a1fa33c1071e29aff3d7040972dbb5481ba215010b3",
"0x7e1be83ac51c7e68110c6984da43885af18bc9fe988a57ada7b2379d0a122563",
"0xdb01b1cb4084a43c9a57bf8a65a58245edee5bbbdcf0573a3626e9290b4a2e6a",
"0x6c97523c89da4c9325fe17d2e879bbd6b4693f3e6d807564de83ccf801e66737",
"0x7511c0b30bd4dfa6f9a4f38793ee11e2a616de5d9d2212024c0875052ef2559e",
"0x6faa338fd78b41f2ecb623d578520b373e0c74caafce95938161dbd95edb0e24",
"0x0622bf3e00fae0e244d138f73d16035cd05aa9e0c4c16d20b36adad77951c2d4",
"0x72e1ed876e0bcdbdd200dbd55a9d7e8248a4c7ca75588681b61f6f76eb980060",
"0x981a052ee33c36c52fc33598c2563ff3698e1efd130090658cb457bb814ecff8",
"0x2b732d67211042b340c1bc49682518bb00dfcaebd0cfe861b5d38df9c127ed64",
"0xfcba6702d24950030403f872be646d058039d735cf297fcedb5daa255d47ce72",
"0xba3bdc1bd47ab43c2d39ee67a512f306e987b577166d7037705a1fda772bbeec",
"0xa39705f9efc0c0b9051742b705dab9fed7a08b3a00ff15583e15de95a9933356",
"0x551658242a3237fda7b61eae6dc40f368ffbbe3e7f292bf1b3d291d1f21a631d",
"0x631783a116fb5af727d2617276bf310e9f018e1f072d9f3d5432773ec29a193a",
"0x7d2bee7cbf5aa7a5247f047b1147f55380e035a5ff1ce958037d96a539fada37",
"0xfbe38f5210d9fc7c3474be4ff932d1ca393a565426f5d1443537e962beabbbca",
"0xfc9b71f941a0a9dafd6356c4a42c369f22144b43f32f5d50fe3d4c1cf3ee3cda",
"0xa4eb11bb0a0e210af085dc446766f4bb0d19dfec04e9d5d0d2c0ee390597906d",
"0x42e8e9e3d4d6de275146369fa7c010a10979793276a4406bbfd77a543809e762",
"0xb2fef38ac3b58b498cdad7d195bdb3604ca0cfc0ca3c7282163636d3022def43",
"0x923269e9a526ddaa446a2e7acaea5189726ff77e664c20a341f6ad2f6b810d5f",
"0x02e876ba6df7c9ddd7a9ad9bbc15f5918b096e299260fc85a8c7ebaa71d7dde5",
"0x660442f393884c6c4b879168ab3c80c57318c6c62a67ba8df3788edf9ad7303f",
"0x37f7ab248fded056ae5ecde87bf51c1f4baea786fc7c9f5b6760ad13c90659ac",
"0x36fda244e2896e45d3a8a9ed67d7c09a2974c75944a7233f571928a497b55f8c",
"0x4914478536196c3c813fe151cdf37097c6dc9e8d5c0cf9b370fe7567905fc4be",
"0xcedb88613a1d6fbc24909963911efbc5ff56ba09377350b5e824123b50d1a910",
"0x236fe31e63e426111507b2f972547255bd12c6f5df9079953a8b8346179bba57",
"0x2f08e1b0ad4024814428237b4f0e7ca5a83257d25a1cb97f42db14307113916f",
"0x41e45a3a2239551e8cb9598fb855f3d8922386c2e004426e294d111a94856b92",
"0xd5d385b54446abfa8c78950aacae52edede3a7a65d9c7515043431a4498e4f85",
"0xf2d2eb5169760d81d16067b9453979783a2feea91dfa253baa3183f2419478b0",
"0xa5aac8d064c4f4cdfdd2c7f7326c1e0260aeb44be48b391616eb01fc6d30c95e",
"0xb2a298085b0a082fc1781aad1abd263e9cc2c5eeeaa70acd88e8bdfbc0be7d15",
"0xe2d19c438ddb9b96e77a9bc70566f49021bb6444569eea3cd039ecab4d61f73a",
"0xa8549fc117d3faba2ca53efb94bbb37e9cb82bed8273e408da5ed47f5df7aab4",
"0x161c898240dd6e0a0a1f1f5948c652a796bb6586995783a35e7ed6c3c02fb82b",
"0x57214b17853934f1a548a7e9942849a04b9220f5b783a9d2be7395108bdc12e7",
"0x7902ef6c69f5d0a3de1e45d8b46aebcf35aa87cc5f4644186f1c34614a429175",
"0xc290a119f495ff04f406c28461e2de50abf92743b7fdd680048e491044fc59b7",
"0x09bf0fa4aa8b65dcc8f937e46287eb2585c85c587b425f8a0af69d02948f35d9",
"0xff20130699483dee0caacca392c2ad58738f61ea2443869616a3bf006e0cd1ad",
"0x937c629f7307f7411a4b1cc5b92f6a1f1f42f716463f15c449c681d16525996f",
"0x7cd028f48f117d8da3d537f0bb0fb0c832d3111d16fc116bd06454ddd513a095",
"0x4bf15bb783cf917375b5494e00ce003d8da01c65fcbac40d44e62a6172f2cca8",
"0xaff5ceacf024e9146631c772e4e87f223a241e789c88ae083da716c9aa47b860",
"0x68c1db9a727678d2018ec98d0bbc369faec2fb1283b479abd5d6f2b1b04036aa",
"0xe70962a032b4cb81910cea9911eef50ede2eeaa6f487f1e9f8fbf88f133249b1",
"0x1bc2bd4440a1412fbf582d167e0d08629ad2bfe0bc0dfaeb5eb7730a4baf007c",
"0x2d4cbafea30b01e466b41f6911deae979f4f5c82dcbdd76f711f7bf9300c23f4",
"0x252e39a51862ebaf28d9b38f9fb842c70b5bf0669ca008b4c83c542e5236a1af",
"0xba04c89c7ec2867d778f8632e7f51e11f06e56004520444ca922eabdab623473",
"0x74b8dc3bf589a6d9051fbed9af3021e8fb775eab0f457cfd5d38b2ec8f88a24c",
"0x8c0a98cd1665f50b702b44e10dfbfaa70f08b65ede72e39306b1d31b75c07afb",
"0xa38c3526f5f6bce7e64a195cf8659160bc7318b8862ba206535626c338485c64",
"0x4ad34e3c6be8cac9be3fba22eb7e99d951baf5827df5ef921f2b01d63862e116",
"0x596670c729beb030c8756bf2ec6c884f9b4edc433a94f5dc5d4d337dbb712d76",
"0x39611d27f11938df810165987ee7edbe87cfb7e4068216cbb45848b4029f8419"
]
},
"accounts": {
@@ -5265,6 +5381,7 @@
}
},
"nodes": [
"enode://f6e37b943bad3a78cb8589b1798d30d210ffd39cfcd2c8f2de4f098467fd49c667980100d919da7ca46cd50505d30989abda87f0b9339377de13d6592c22caf8@34.198.49.72:30303",
"enode://56abaf065581a5985b8c5f4f88bd202526482761ba10be9bfdcd14846dd01f652ec33fde0f8c0fd1db19b59a4c04465681fcef50e11380ca88d25996191c52de@40.71.221.215:30303",
"enode://d07827483dc47b368eaf88454fb04b41b7452cf454e194e2bd4c14f98a3278fed5d819dbecd0d010407fc7688d941ee1e58d4f9c6354d3da3be92f55c17d7ce3@52.166.117.77:30303",
"enode://38e6e7fd416293ed120d567a2675fe078c0205ab0671abf16982ce969823bd1f3443d590c18b321dfae7dcbe1f6ba98ef8702f255c3c9822a188abb82c53adca@51.77.66.187:30303",

File diff suppressed because it is too large Load Diff

View File

@@ -34,7 +34,10 @@
"eip140Transition": "0x0",
"eip211Transition": "0x0",
"eip214Transition": "0x0",
"eip658Transition": "0x0"
"eip658Transition": "0x0",
"eip145Transition": 8582254,
"eip1014Transition": 8582254,
"eip1052Transition": 8582254
},
"genesis": {
"seal": {

View File

@@ -0,0 +1,903 @@
{
"name": "Rinkeby",
"dataDir": "rinkeby",
"engine": {
"clique": {
"params": {
"period": 15,
"epoch": 30000
}
}
},
"params": {
"accountStartNonce": "0x0",
"chainID": "0x4",
"eip140Transition": "0xfcc25",
"eip145Transition": "0x37db77",
"eip150Transition": "0x2",
"eip155Transition": "0x3",
"eip160Transition": "0x0",
"eip161abcTransition": "0x0",
"eip161dTransition": "0x0",
"eip211Transition": "0xfcc25",
"eip214Transition": "0xfcc25",
"eip658Transition": "0xfcc25",
"eip1014Transition": "0x37db77",
"eip1052Transition": "0x37db77",
"eip1283Transition": "0x37db77",
"eip1283DisableTransition": "0x41efd2",
"gasLimitBoundDivisor": "0x400",
"maxCodeSize": "0x6000",
"maxCodeSizeTransition": "0x0",
"maximumExtraDataSize": "0xffff",
"minGasLimit": "0x1388",
"networkID": "0x4"
},
"genesis": {
"author": "0x0000000000000000000000000000000000000000",
"difficulty": "0x1",
"extraData": "0x52657370656374206d7920617574686f7269746168207e452e436172746d616e42eb768f2244c8811c63729a21a3569731535f067ffc57839b00206d1ad20c69a1981b489f772031b279182d99e65703f0076e4812653aab85fca0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x47b760",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"seal": {
"ethereum": {
"nonce": "0x0000000000000000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
},
"timestamp": "0x58ee40ba"
},
"nodes": [
"enode://a24ac7c5484ef4ed0c5eb2d36620ba4e4aa13b8c84684e1b4aab0cebea2ae45cb4d375b77eab56516d34bfbd3c1a833fc51296ff084b770b94fb9028c4d25ccf@52.169.42.101:30303",
"enode://343149e4feefa15d882d9fe4ac7d88f885bd05ebb735e547f12e12080a9fa07c8014ca6fd7f373123488102fe5e34111f8509cf0b7de3f5b44339c9f25e87cb8@52.3.158.184:30303",
"enode://b6b28890b006743680c52e64e0d16db57f28124885595fa03a562be1d2bf0f3a1da297d56b13da25fb992888fd556d4c1a27b1f39d531bde7de1921c90061cc6@159.89.28.211:30303"
],
"accounts": {
"0x0000000000000000000000000000000000000000": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000001": {
"balance": "0x1",
"builtin": {
"name": "ecrecover",
"pricing": {
"linear": {
"base": 3000,
"word": 0
}
}
}
},
"0x0000000000000000000000000000000000000002": {
"balance": "0x1",
"builtin": {
"name": "sha256",
"pricing": {
"linear": {
"base": 60,
"word": 12
}
}
}
},
"0x0000000000000000000000000000000000000003": {
"balance": "0x1",
"builtin": {
"name": "ripemd160",
"pricing": {
"linear": {
"base": 600,
"word": 120
}
}
}
},
"0x0000000000000000000000000000000000000004": {
"balance": "0x1",
"builtin": {
"name": "identity",
"pricing": {
"linear": {
"base": 15,
"word": 3
}
}
}
},
"0x0000000000000000000000000000000000000005": {
"balance": "0x1",
"builtin": {
"name": "modexp",
"activate_at": "0xfcc25",
"pricing": {
"modexp": {
"divisor": 20
}
}
}
},
"0x0000000000000000000000000000000000000006": {
"balance": "0x1",
"builtin": {
"name": "alt_bn128_add",
"activate_at": "0xfcc25",
"pricing": {
"linear": {
"base": 500,
"word": 0
}
}
}
},
"0x0000000000000000000000000000000000000007": {
"balance": "0x1",
"builtin": {
"name": "alt_bn128_mul",
"activate_at": "0xfcc25",
"pricing": {
"linear": {
"base": 40000,
"word": 0
}
}
}
},
"0x0000000000000000000000000000000000000008": {
"balance": "0x1",
"builtin": {
"name": "alt_bn128_pairing",
"activate_at": "0xfcc25",
"pricing": {
"alt_bn128_pairing": {
"base": 100000,
"pair": 80000
}
}
}
},
"0x0000000000000000000000000000000000000009": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000000a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000000b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000000c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000000d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000000e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000000f": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000010": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000011": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000012": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000013": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000014": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000015": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000016": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000017": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000018": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000019": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000001a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000001b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000001c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000001d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000001e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000001f": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000020": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000021": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000022": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000023": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000024": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000025": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000026": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000027": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000028": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000029": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000002a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000002b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000002c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000002d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000002e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000002f": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000030": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000031": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000032": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000033": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000034": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000035": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000036": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000037": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000038": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000039": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000003a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000003b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000003c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000003d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000003e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000003f": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000040": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000041": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000042": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000043": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000044": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000045": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000046": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000047": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000048": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000049": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000004a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000004b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000004c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000004d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000004e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000004f": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000050": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000051": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000052": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000053": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000054": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000055": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000056": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000057": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000058": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000059": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000005a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000005b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000005c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000005d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000005e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000005f": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000060": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000061": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000062": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000063": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000064": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000065": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000066": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000067": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000068": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000069": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000006a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000006b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000006c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000006d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000006e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000006f": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000070": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000071": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000072": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000073": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000074": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000075": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000076": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000077": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000078": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000079": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000007a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000007b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000007c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000007d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000007e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000007f": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000080": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000081": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000082": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000083": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000084": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000085": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000086": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000087": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000088": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000089": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000008a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000008b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000008c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000008d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000008e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000008f": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000090": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000091": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000092": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000093": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000094": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000095": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000096": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000097": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000098": {
"balance": "0x1"
},
"0x0000000000000000000000000000000000000099": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000009a": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000009b": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000009c": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000009d": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000009e": {
"balance": "0x1"
},
"0x000000000000000000000000000000000000009f": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a0": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a1": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a2": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a3": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a4": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a5": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a6": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a7": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a8": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000a9": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000aa": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ab": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ac": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ad": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ae": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000af": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b0": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b1": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b2": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b3": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b4": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b5": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b6": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b7": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b8": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000b9": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ba": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000bb": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000bc": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000bd": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000be": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000bf": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c0": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c1": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c2": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c3": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c4": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c5": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c6": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c7": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c8": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000c9": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ca": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000cb": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000cc": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000cd": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ce": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000cf": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d0": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d1": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d2": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d3": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d4": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d5": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d6": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d7": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d8": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000d9": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000da": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000db": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000dc": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000dd": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000de": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000df": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e0": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e1": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e2": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e3": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e4": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e5": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e6": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e7": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e8": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000e9": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ea": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000eb": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ec": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ed": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ee": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ef": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f0": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f1": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f2": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f3": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f4": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f5": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f6": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f7": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f8": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000f9": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000fa": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000fb": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000fc": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000fd": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000fe": {
"balance": "0x1"
},
"0x00000000000000000000000000000000000000ff": {
"balance": "0x1"
},
"0x31b98d14007bdee637298086988a0bbd31184523": {
"balance": "0x200000000000000000000000000000000000000000000000000000000000000"
}
}
}

View File

@@ -62,8 +62,8 @@
"gasLimit": "0x1000000"
},
"hardcodedSync": {
"header": "f90217a058893ba2a7f3d1625239b0ffab5b58219412b5fb51a608fc6ae7ff012496db9ba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942b126e450158f14add6770739a2e6b4037526817a0a46d5b8474c625b4efd3d1d2864d7790770737587aa926fb223945d55a1d0da8a04ff0c821428157d6a4ace26e17d775eac4f42cc7d777898ded413780207fda11a0777f1c1c378807634128348e4f0eeca6a0e7f516ea411690ca04266323f671a4b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000844737e14e834dd801837a1200830186a0845c76311499d883010816846765746888676f312e31312e35856c696e7578a0676e77abeb493056c28a2d8fcd1238da73a29c9d915441fd8b5e36f6e910fa5d8803afeb22c339444f",
"totalDifficulty": "18334236703652990",
"header": "f9021aa0a8da98b6ef1e12b6c49e85b0e965f1ed1688f5e3605f06bb3c6ce4f857aa0bc6a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794635b4764d1939dfacd3a8014726159abc277becca0d03c319fe68a91e22fb3b945a8dfc73b817976e29cf57e6c8425e6a02e9bf034a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000849fe1546f8350d001837a121d80845c9d55f29fde8302020b8f5061726974792d457468657265756d86312e33322e30826c69a04bf72e97bcf64717bfd655e2bca9ed1a5253cce5373268729161b1786ca4710488db3c50627f9321c4",
"totalDifficulty": "18787961645682286",
"CHTs": [
"0x614648fc0a459451850bdfe353a932b5ff824e1b568478394f78b3ed5427e37a",
"0x1eae561c582dbb7f4e041998e084e165d0332c915d3a6da367638a8d24f3fafc",
@@ -2555,7 +2555,102 @@
"0x563d7efb4175fc12dab431175b5097186c2379a5aca1901e39d641d02865d426",
"0x1a55cf9842f9008e0730ae9fc6af9f288edba323803d0ae787fc0fdda99be8c9",
"0xccdf47cee7142cad27bbf224f0afd1a6e5178345cab510f2f8ee27115ab27ff7",
"0xc5b3582937ad993c5c234d059e6cd3b98f2fa4e3fe4ad591ecb6ae710b51fee9"
"0xc5b3582937ad993c5c234d059e6cd3b98f2fa4e3fe4ad591ecb6ae710b51fee9",
"0xd651ab199355d61c49e63259e6a20d17bf72b27891271e5175a24c23fb2dc29c",
"0x800e1e33b0cd48afc6f8f7c69b85902ad93e94bb290b35a862cbad67706a2f3d",
"0x57c7349a6b630cb52c3c1205165df428ed51e25cc167c08739f86bfa46c69e48",
"0xb393d362daff182dafcce65eda9038fc0c8908b3cb1ec1a1218570211c34e142",
"0xb2f49f7a836cd0db9e4743158ff80dd97d23de7a39a0438d19c79c355339c43c",
"0x3f46776ec25b5c67468c32c1b2ca02910a7f46b4b62b5dc5d0cc6b9d3381b958",
"0x754c4ea722e501668aa48d6151ff423263b8a4e2f33b9e44e189ee4e78462741",
"0x12e79ee2724763a8a7f9196bf4d0e855e0ae3f75f5a697d90a263bf562acc5a3",
"0x407b168fea70128a8090ca86274b0b8e7965f16d54ea2b3bbabb378485b22a02",
"0x0d1557ad0cb1466965e6ee86c5ce887eedf462dbec2e719c5f396f8ed95edf08",
"0x29c3a0db9f83698e6ae703174dbeec06f3d2055eb933799e4ae3bf73f4570dde",
"0x8ade20e56fcacb40f54259696bea1aa04d839b88c503d6775d7b4491e0f9e7fa",
"0x327ef0f173632c5049988b312b1f49e9948b02125f70e117ea127088191c32d5",
"0x2989c11c234b7fc5901e168d7adfa655ff6165098eb94d244b623ba43c6abbd6",
"0x10b56dc8f023de6a8f97696dfe2993b56156a9b35f671438fee5830f52b633b5",
"0x46cd37fffe94a01297f2dcef322ae72f58bbf9f58bc9f930cbf56e73f8d5ce13",
"0x2240214683eafc37396f3078446b43ae96bc576e45db650b953ff87a895ee7d7",
"0x0db4d500e5755cba5b962f6b83942e72fd1504cf52531916084852179669a08d",
"0xafc686a8325a30966db0f54b64a4e7235ea54e300d280a4d2a502651a53424b5",
"0x59d46f6fb8eadcf18e31c9fd0da6844d63a2dc19eeeaf9ad5b80113aca5bc42a",
"0x153ae496364bf7c34c8c967e044cef69e401f0e4aff27b04808e2c299dcf15a8",
"0xc85b8d3156729c7f8ff1989f320464144f4918140d608cf03e7dfd5b51ec2acf",
"0x78fd0613f6f5291d4131152225fbded5464841a119d854a7550a1f178a8cdfc7",
"0x763dc1a000b949a45f792515fed6af70047641fa3d7beeb50b141c27b4f8cd33",
"0x42567a1e6caadaa10a13feff343ae1e2a903564affacc48aebc14f257db58ee1",
"0x62c208337234d101cc95cb6be54c17631e26c956758493f5bb7978faf0ace984",
"0x7977aec997a3029025ef789d3492755c80c2d028046aae8c4b926f247e1981d9",
"0xf927505a0c29231ed187a884af15a82dbc48a1cb002f6d91496f6569c673682d",
"0xefd2c54f6d2483a3dd7b994d8afa5441cfffa956d7da6e81bbd1691e07ac7519",
"0x7bcf94d8927a39dd00558763cdd2edaf40d55728d720dccfa0f5e1e827079cc0",
"0x19c7e5115ec25b14bd85e3d368e15d2bbe60451ed9a02f03770a3e845521b77c",
"0x60e32d48de6979c70dcb3e3f068fc3632aba5844703d50851a34975338b3a837",
"0x6722f01dc1d6dd1f0678e5b527155beb0616e33887697a56ef4cc1bac642f394",
"0x59bf17368d69e0379f0f20ec1b1b856298b8d6b4c36354ee765c8a894e58ab9b",
"0xe2559e7b67a15a3ddfbf1ddc597a1309d1fd780fe26da28aace16ad31754883c",
"0xbf687ac704bf02a3877e72f738691bf5027c21f64c68a50235876a8d015ae682",
"0xde01838df621b7368adf4fda268c827dfaa6753a39d51956c0445a2244585ec1",
"0x4ba14d3860d1dee44904719e45a5bfe54dd1e4c9bdafd0a41279e432a021f2e6",
"0xa2380cb32538cc80e07fda5575ecd7b35e0c12932687bd8002da652ad8c16dc2",
"0x82d0f5c8421d6803e52e3d6a37eea0cd978686792a2f6d175d77e9c75fb4ad86",
"0x23701b29d07c64c998ee4bf8199d5ac0f3d9724af2544cc29665a1d92a6dadce",
"0x8bbd490220c823506e111c668f923d18addf5a23d9b5244103cc135c4335f23d",
"0x190506f2d9decb8f9423662f406e61c99606abdcb369e25a1a89c2bdc44c6158",
"0xb9504b090b276cbbf86349bc4dbb66b46a42ce6ae8d44d5cd7f39773fdf6112a",
"0x38fc273344dc7230790963dfb3dedfabe142c18886d6542d77ace8ed6d117c4f",
"0xc76929e9a3a984f6ab6395c4811f007eb6d73a86fe62f8a1c02e860769f2bcde",
"0xc4fc2465f71d06102d232858cfd9737e6e82311a45b1cb2ac203de80c881a2f4",
"0x34427ee5534de01e7f0510b87e6f45aac6210897472978aee3c051c39776c561",
"0xec4f3c6349dac1e7e43b0541b1132b3d0cc8bd422436f31832184d1aa6f9c822",
"0x024a848067a1156852c78495581392774b00f22e32021ca531afeab1aafb683e",
"0x9bdf793e30326a181d3d8fb3f27818475b755e3d1fea200d8c514cf17024979a",
"0x55a1d92354a31354b4b1d9366e98b27c0467b01a108d67dab7feeeda23f981d9",
"0x74614ac3de92173d07434dd80d83aad5c1d551127896298808ad7fba96051e06",
"0x7bdb77183ca1e7f50d292e50ef701ad3bfff3e6e28d36629c5325da03cb8d013",
"0x3a35dc3d12de1053d204410a577b9e5c36d32fbda761f797aee248c27f7dbb02",
"0x430aaeb1dc02bb792375d1702999cda7c384dde1c6f46ef26f1e26e5a55dfd87",
"0xe12805d1713ba730fec6aae824bdcd0a896c6d5e12b9bfa5b6e0a2c2be251c17",
"0x5a297bd3be2352e56136db83a76c7041ef825128152366b2d8f032abb1d6656f",
"0x111782d82f50ea25d684af38689cea53319f1a88557d82c57e46ee5e75f99c05",
"0xe12520cda10064d74fdefba22b5ff4c5eb95508f77fd7c8c3fe82fb89e165bf6",
"0x6af12e8f4db19aee3865c3d681073e7433d902832bc651b8fc3f5fd038c8bca6",
"0x82a4a2ce19ca3fd99007279d62dadba547b6818607800e963b3bc53c5541298a",
"0xbf3a444d1b15d01a29ea22d05e71021ee3581338ecc9e770ee23ab6549a19d55",
"0x745ff92172b5c83cdd69265b919028b350ef95a01c84810366d630162fd9b07f",
"0x6128cd2ff1be9e56396a676362a2049f3e670c70ad2a77be724c090fd4085f0b",
"0x8ffc6bf8165e52ecf30ec955d4be1bb093e6074c92a527382a8892ffa3d3e7f7",
"0xd65bc11ef24c0fa476640d9effdc57030a86f547b7aa79b209954a6abf4072c4",
"0xcd5b5e184a5c0d1c5bdd12f80736ed1a4530210b4ef5f35dacd3feba722a334a",
"0xa80657ecf79ef03fb919bf312e02d94ab528c1b5c3858332d9bf82f807b1c232",
"0xc67dfe4aca5001e97ba6f401f15b72be85ae45972ba98b965a6dd4954d5c2386",
"0x59201e892aeab9e40aef69945585b81b47a7444ed61ba6c6e23e006103ed7edd",
"0xf535c920c5316f12f0bfedc298fbad028dd84161927414b14243c4c5ddd4f4f1",
"0x66c6e42c8137c043eb49528c718b10e5dbad9164bd3ffcc6b55b4b0501dc507b",
"0xa60b9485cb54818e0b0bfe4faeca923915f85bbac0525d09d96f375d0b2b9f81",
"0x8f9377dddacb6ed605c8ed8ed2bc6e2323a4e5d0c9b29bccdfbd27f57a9ec315",
"0xc48a1940c424c2df4803ba8d5573066ce4bbf0e0fbdaa87abcb2d2f51b0a4602",
"0xc7bce918e9f897aeb1351d2c9cbc2fbc8fd674017cb25c49846b05d609f00ed9",
"0xcdaa86e0c026c91954c6305cb7ce6010560f691a2667baf0e95bc18cd3e067df",
"0xf131e0910a8088fc5b0b1d2e93e31632eec67fa88f75bc4f9c3c1b0a317e1d54",
"0xb4f8d72a85c4c2261c7b00f43b96d7d749d0e53359993f52517da36de4c9559b",
"0x73f84bb4774a81b39b3a10d18c7a2404d21f3efd26301dbb7c8136e96304281e",
"0x5559435a987f1444e4ec78b8530009e49c52431b37c7e9f80ce2e056d44e876a",
"0x070664d11ee10c4e0475a7ece219eb0e606e055ee0fa1266b669e593b5ba1d87",
"0xfdfafeba7b5551d1e2d6f179be5ddfdbd0350bd2e9dfea40e272fb608549e8c2",
"0x50a1356bab9b56d8ed46a3e8f55b8a16af42df6b15fcc68aa548216de484c7eb",
"0x681161a307552ff12175074601005bae0c6f7b38cfa6dcb87975a1df205e28d5",
"0x2b39456efc2e8863197c95a4d6eef5069612cc2aa6414f0991393ffa672a1a15",
"0x571b916a82371fafcb456524655758bd42b4f7b768e13807a1a995e642ec205c",
"0xb2821504201eea0e6040a131a709547fc9afb44ba7bfa6a188201735753ba3b7",
"0xb16a8af1bfdde1fae0e28f29c6db0b361840df4b55e73bddffbc1cc11bcc5584",
"0x1df38b594f536cee38acad293a818bf83fc67830fc71bc19790d7733a2caab60",
"0xebb3e8f76f3b6a95285154dc11d4bd94ac4c3a150383ed69f5373499b1983dc3",
"0xb0919ed300acac5f912f01611a428861db27ffb8129a80495f735f0ac608ab35",
"0x2ee321d9d805b78a97210df2977ab62b352705e308773b90e0f4e923adec377c",
"0xee00cb02e9b86978ae10b119924bbe6c38f730c1d1b621d32c9d697e11105871"
]
},
"nodes": [

File diff suppressed because it is too large Load Diff

View File

@@ -14,17 +14,18 @@
// You should have received a copy of the GNU General Public License
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
// Silence: `use of deprecated item 'std::error::Error::cause': replaced by Error::source, which can support downcasting`
// https://github.com/paritytech/parity-ethereum/issues/10302
#![allow(deprecated)]
use ethcore;
use io;
use ethcore_private_tx;
error_chain! {
links {
PrivateTransactions(ethcore_private_tx::Error, ethcore_private_tx::ErrorKind);
}
foreign_links {
Ethcore(ethcore::error::Error);
IoError(io::IoError);
PrivateTransactions(ethcore_private_tx::Error);
}
}

View File

@@ -31,7 +31,7 @@
//! `ExecutedBlock` is an underlaying data structure used by all structs above to store block
//! related info.
use std::cmp;
use std::{cmp, ops};
use std::collections::HashSet;
use std::sync::Arc;
@@ -52,7 +52,6 @@ use vm::{EnvInfo, LastHashes};
use hash::keccak;
use rlp::{RlpStream, Encodable, encode_list};
use types::transaction::{SignedTransaction, Error as TransactionError};
use types::block::Block;
use types::header::{Header, ExtendedHeader};
use types::receipt::{Receipt, TransactionOutcome};
@@ -155,69 +154,15 @@ impl ExecutedBlock {
}
}
/// Trait for a object that is a `ExecutedBlock`.
pub trait IsBlock {
/// Get the `ExecutedBlock` associated with this object.
fn block(&self) -> &ExecutedBlock;
/// Get the base `Block` object associated with this.
fn to_base(&self) -> Block {
Block {
header: self.header().clone(),
transactions: self.transactions().iter().cloned().map(Into::into).collect(),
uncles: self.uncles().to_vec(),
}
}
/// Get the header associated with this object's block.
fn header(&self) -> &Header { &self.block().header }
/// Get the final state associated with this object's block.
fn state(&self) -> &State<StateDB> { &self.block().state }
/// Get all information on transactions in this block.
fn transactions(&self) -> &[SignedTransaction] { &self.block().transactions }
/// Get all information on receipts in this block.
fn receipts(&self) -> &[Receipt] { &self.block().receipts }
/// Get all uncles in this block.
fn uncles(&self) -> &[Header] { &self.block().uncles }
}
/// Trait for an object that owns an `ExecutedBlock`
pub trait Drain {
/// Returns `ExecutedBlock`
fn drain(self) -> ExecutedBlock;
}
impl IsBlock for ExecutedBlock {
fn block(&self) -> &ExecutedBlock { self }
}
impl ::parity_machine::LiveBlock for ExecutedBlock {
type Header = Header;
fn header(&self) -> &Header {
&self.header
}
fn uncles(&self) -> &[Header] {
&self.uncles
}
}
impl ::parity_machine::Transactions for ExecutedBlock {
type Transaction = SignedTransaction;
fn transactions(&self) -> &[SignedTransaction] {
&self.transactions
}
}
impl<'x> OpenBlock<'x> {
/// Create a new `OpenBlock` ready for transaction pushing.
pub fn new<'a>(
pub fn new<'a, I: IntoIterator<Item = ExtendedHeader>>(
engine: &'x EthEngine,
factories: Factories,
tracing: bool,
@@ -228,7 +173,7 @@ impl<'x> OpenBlock<'x> {
gas_range_target: (U256, U256),
extra_data: Bytes,
is_epoch_begin: bool,
ancestry: &mut Iterator<Item=ExtendedHeader>,
ancestry: I,
) -> Result<Self, Error> {
let number = parent.number() + 1;
let state = State::from_existing(db, parent.state_root().clone(), engine.account_start_nonce(number), factories)?;
@@ -250,7 +195,7 @@ impl<'x> OpenBlock<'x> {
engine.populate_from_parent(&mut r.block.header, parent);
engine.machine().on_new_block(&mut r.block)?;
engine.on_new_block(&mut r.block, is_epoch_begin, ancestry)?;
engine.on_new_block(&mut r.block, is_epoch_begin, &mut ancestry.into_iter())?;
Ok(r)
}
@@ -270,7 +215,7 @@ impl<'x> OpenBlock<'x> {
/// NOTE Will check chain constraints and the uncle number but will NOT check
/// that the header itself is actually valid.
pub fn push_uncle(&mut self, valid_uncle_header: Header) -> Result<(), BlockError> {
let max_uncles = self.engine.maximum_uncle_count(self.block.header().number());
let max_uncles = self.engine.maximum_uncle_count(self.block.header.number());
if self.block.uncles.len() + 1 > max_uncles {
return Err(BlockError::TooManyUncles(OutOfBounds{
min: None,
@@ -284,11 +229,6 @@ impl<'x> OpenBlock<'x> {
Ok(())
}
/// Get the environment info concerning this block.
pub fn env_info(&self) -> EnvInfo {
self.block.env_info()
}
/// Push a transaction into the block.
///
/// If valid, it will be executed, and archived together with the receipt.
@@ -297,7 +237,7 @@ impl<'x> OpenBlock<'x> {
return Err(TransactionError::AlreadyImported.into());
}
let env_info = self.env_info();
let env_info = self.block.env_info();
let outcome = self.block.state.apply(&env_info, self.engine.machine(), &t, self.block.traces.is_enabled())?;
self.block.transactions_set.insert(h.unwrap_or_else(||t.hash()));
@@ -344,7 +284,6 @@ impl<'x> OpenBlock<'x> {
self.block.header.set_difficulty(*header.difficulty());
self.block.header.set_gas_limit(*header.gas_limit());
self.block.header.set_timestamp(header.timestamp());
self.block.header.set_author(*header.author());
self.block.header.set_uncles_hash(*header.uncles_hash());
self.block.header.set_transactions_root(*header.transactions_root());
// TODO: that's horrible. set only for backwards compatibility
@@ -394,22 +333,39 @@ impl<'x> OpenBlock<'x> {
pub fn block_mut(&mut self) -> &mut ExecutedBlock { &mut self.block }
}
impl<'x> IsBlock for OpenBlock<'x> {
fn block(&self) -> &ExecutedBlock { &self.block }
impl<'a> ops::Deref for OpenBlock<'a> {
type Target = ExecutedBlock;
fn deref(&self) -> &Self::Target {
&self.block
}
}
impl IsBlock for ClosedBlock {
fn block(&self) -> &ExecutedBlock { &self.block }
impl ops::Deref for ClosedBlock {
type Target = ExecutedBlock;
fn deref(&self) -> &Self::Target {
&self.block
}
}
impl IsBlock for LockedBlock {
fn block(&self) -> &ExecutedBlock { &self.block }
impl ops::Deref for LockedBlock {
type Target = ExecutedBlock;
fn deref(&self) -> &Self::Target {
&self.block
}
}
impl ops::Deref for SealedBlock {
type Target = ExecutedBlock;
fn deref(&self) -> &Self::Target {
&self.block
}
}
impl ClosedBlock {
/// Get the hash of the header without seal arguments.
pub fn hash(&self) -> H256 { self.header().bare_hash() }
/// Turn this into a `LockedBlock`, unable to be reopened again.
pub fn lock(self) -> LockedBlock {
LockedBlock {
@@ -443,25 +399,25 @@ impl LockedBlock {
self.block.header.set_receipts_root(
ordered_trie_root(self.block.receipts.iter().map(|r| r.rlp_bytes()))
);
// compute hash and cache it.
self.block.header.compute_hash();
}
/// Get the hash of the header without seal arguments.
pub fn hash(&self) -> H256 { self.header().bare_hash() }
/// Provide a valid seal in order to turn this into a `SealedBlock`.
///
/// NOTE: This does not check the validity of `seal` with the engine.
pub fn seal(self, engine: &EthEngine, seal: Vec<Bytes>) -> Result<SealedBlock, BlockError> {
let expected_seal_fields = engine.seal_fields(self.header());
pub fn seal(self, engine: &EthEngine, seal: Vec<Bytes>) -> Result<SealedBlock, Error> {
let expected_seal_fields = engine.seal_fields(&self.header);
let mut s = self;
if seal.len() != expected_seal_fields {
return Err(BlockError::InvalidSealArity(
Mismatch { expected: expected_seal_fields, found: seal.len() }));
Err(BlockError::InvalidSealArity(Mismatch {
expected: expected_seal_fields,
found: seal.len()
}))?;
}
s.block.header.set_seal(seal);
engine.on_seal_block(&mut s.block)?;
s.block.header.compute_hash();
Ok(SealedBlock {
block: s.block
})
@@ -470,6 +426,7 @@ impl LockedBlock {
/// Provide a valid seal in order to turn this into a `SealedBlock`.
/// This does check the validity of `seal` with the engine.
/// Returns the `ClosedBlock` back again if the seal is no good.
/// TODO(https://github.com/paritytech/parity-ethereum/issues/10407): This is currently only used in POW chain call paths, we should really merge it with seal() above.
pub fn try_seal(
self,
engine: &EthEngine,
@@ -510,12 +467,8 @@ impl Drain for SealedBlock {
}
}
impl IsBlock for SealedBlock {
fn block(&self) -> &ExecutedBlock { &self.block }
}
/// Enact the block given by block header, transactions and uncles
fn enact(
pub(crate) fn enact(
header: Header,
transactions: Vec<SignedTransaction>,
uncles: Vec<Header>,
@@ -528,13 +481,12 @@ fn enact(
is_epoch_begin: bool,
ancestry: &mut Iterator<Item=ExtendedHeader>,
) -> Result<LockedBlock, Error> {
{
if ::log::max_level() >= ::log::Level::Trace {
let s = State::from_existing(db.boxed_clone(), parent.state_root().clone(), engine.account_start_nonce(parent.number() + 1), factories.clone())?;
trace!(target: "enact", "num={}, root={}, author={}, author_balance={}\n",
header.number(), s.root(), header.author(), s.balance(&header.author())?);
}
}
// For trace log
let trace_state = if log_enabled!(target: "enact", ::log::Level::Trace) {
Some(State::from_existing(db.boxed_clone(), parent.state_root().clone(), engine.account_start_nonce(parent.number() + 1), factories.clone())?)
} else {
None
};
let mut b = OpenBlock::new(
engine,
@@ -543,13 +495,23 @@ fn enact(
db,
parent,
last_hashes,
Address::new(),
// Engine such as Clique will calculate author from extra_data.
// this is only important for executing contracts as the 'executive_author'.
engine.executive_author(&header)?,
(3141562.into(), 31415620.into()),
vec![],
is_epoch_begin,
ancestry,
)?;
if let Some(ref s) = trace_state {
let env = b.env_info();
let root = s.root();
let author_balance = s.balance(&env.author)?;
trace!(target: "enact", "num={}, root={}, author={}, author_balance={}\n",
b.block.header.number(), root, env.author, author_balance);
}
b.populate_from(&header);
b.push_transactions(transactions)?;
@@ -615,6 +577,7 @@ mod tests {
last_hashes: Arc<LastHashes>,
factories: Factories,
) -> Result<LockedBlock, Error> {
let block = Unverified::from_rlp(block_bytes)?;
let header = block.header;
let transactions: Result<Vec<_>, Error> = block
@@ -644,7 +607,7 @@ mod tests {
(3141562.into(), 31415620.into()),
vec![],
false,
&mut Vec::new().into_iter(),
None,
)?;
b.populate_from(&header);
@@ -669,7 +632,7 @@ mod tests {
) -> Result<SealedBlock, Error> {
let header = Unverified::from_rlp(block_bytes.clone())?.header;
Ok(enact_bytes(block_bytes, engine, tracing, db, parent, last_hashes, factories)?
.seal(engine, header.seal().to_vec())?)
.seal(engine, header.seal().to_vec())?)
}
#[test]
@@ -679,7 +642,7 @@ mod tests {
let genesis_header = spec.genesis_header();
let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b = OpenBlock::new(&*spec.engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
let b = OpenBlock::new(&*spec.engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false, None).unwrap();
let b = b.close_and_lock().unwrap();
let _ = b.seal(&*spec.engine, vec![]);
}
@@ -693,7 +656,7 @@ mod tests {
let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap()
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![], false, None).unwrap()
.close_and_lock().unwrap().seal(engine, vec![]).unwrap();
let orig_bytes = b.rlp_bytes();
let orig_db = b.drain().state.drop().1;
@@ -717,7 +680,7 @@ mod tests {
let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let mut open_block = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
let mut open_block = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![], false, None).unwrap();
let mut uncle1_header = Header::new();
uncle1_header.set_extra_data(b"uncle1".to_vec());
let mut uncle2_header = Header::new();

View File

@@ -25,8 +25,7 @@ use blockchain::{BlockReceipts, BlockChain, BlockChainDB, BlockProvider, TreeRou
use bytes::Bytes;
use call_contract::{CallContract, RegistryInfo};
use ethcore_miner::pool::VerifiedTransaction;
use ethcore_miner::service_transaction_checker::ServiceTransactionChecker;
use ethereum_types::{H256, Address, U256};
use ethereum_types::{H256, H264, Address, U256};
use evm::Schedule;
use hash::keccak;
use io::IoChannel;
@@ -45,7 +44,7 @@ use types::receipt::{Receipt, LocalizedReceipt};
use types::{BlockNumber, header::{Header, ExtendedHeader}};
use vm::{EnvInfo, LastHashes};
use block::{IsBlock, LockedBlock, Drain, ClosedBlock, OpenBlock, enact_verified, SealedBlock};
use block::{LockedBlock, Drain, ClosedBlock, OpenBlock, enact_verified, SealedBlock};
use client::ancient_import::AncientVerifier;
use client::{
Nonce, Balance, ChainInfo, BlockInfo, TransactionInfo,
@@ -61,7 +60,7 @@ use client::{
IoClient, BadBlocks,
};
use client::bad_blocks;
use engines::{EthEngine, EpochTransition, ForkChoice, EngineError};
use engines::{MAX_UNCLE_AGE, EthEngine, EpochTransition, ForkChoice, EngineError};
use engines::epoch::PendingTransition;
use error::{
ImportErrorKind, ExecutionError, CallError, BlockError,
@@ -87,7 +86,7 @@ pub use types::blockchain_info::BlockChainInfo;
pub use types::block_status::BlockStatus;
pub use blockchain::CacheSize as BlockChainCacheSize;
pub use verification::QueueInfo as BlockQueueInfo;
use db::Writable;
use db::{Writable, Readable, keys::BlockDetails};
use_contract!(registry, "res/contracts/registrar.json");
@@ -298,19 +297,11 @@ impl Importer {
match self.check_and_lock_block(&bytes, block, client) {
Ok((closed_block, pending)) => {
if self.engine.is_proposal(&header) {
self.block_queue.mark_as_good(&[hash]);
proposed_blocks.push(bytes);
} else {
imported_blocks.push(hash);
let transactions_len = closed_block.transactions().len();
let route = self.commit_block(closed_block, &header, encoded::Block::new(bytes), pending, client);
import_results.push(route);
client.report.write().accrue_block(&header, transactions_len);
}
imported_blocks.push(hash);
let transactions_len = closed_block.transactions.len();
let route = self.commit_block(closed_block, &header, encoded::Block::new(bytes), pending, client);
import_results.push(route);
client.report.write().accrue_block(&header, transactions_len);
},
Err(err) => {
self.bad_blocks.report(bytes, format!("{:?}", err));
@@ -407,6 +398,7 @@ impl Importer {
let db = client.state_db.read().boxed_clone_canon(header.parent_hash());
let is_epoch_begin = chain.epoch_transition(parent.number(), *header.parent_hash()).is_some();
let enact_result = enact_verified(
block,
engine,
@@ -431,13 +423,13 @@ impl Importer {
// if the expected receipts root header does not match.
// (i.e. allow inconsistency in receipts outcome before the transition block)
if header.number() < engine.params().validate_receipts_transition
&& header.receipts_root() != locked_block.block().header().receipts_root()
&& header.receipts_root() != locked_block.header.receipts_root()
{
locked_block.strip_receipts_outcomes();
}
// Final Verification
if let Err(e) = self.verifier.verify_block_final(&header, locked_block.block().header()) {
if let Err(e) = self.verifier.verify_block_final(&header, &locked_block.header) {
warn!(target: "client", "Stage 5 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e);
bail!(e);
}
@@ -445,8 +437,8 @@ impl Importer {
let pending = self.check_epoch_end_signal(
&header,
bytes,
locked_block.receipts(),
locked_block.state().db(),
&locked_block.receipts,
locked_block.state.db(),
client
)?;
@@ -1149,7 +1141,7 @@ impl Client {
pub fn take_snapshot<W: snapshot_io::SnapshotWriter + Send>(&self, writer: W, at: BlockId, p: &snapshot::Progress) -> Result<(), EthcoreError> {
let db = self.state_db.read().journal_db().boxed_clone();
let best_block_number = self.chain_info().best_block_number;
let block_number = self.block_number(at).ok_or(snapshot::Error::InvalidStartingBlock(at))?;
let block_number = self.block_number(at).ok_or_else(|| snapshot::Error::InvalidStartingBlock(at))?;
if db.is_pruned() && self.pruning_info().earliest_state > block_number {
return Err(snapshot::Error::OldBlockPrunedDB.into());
@@ -1335,37 +1327,60 @@ impl BlockChainReset for Client {
fn reset(&self, num: u32) -> Result<(), String> {
if num as u64 > self.pruning_history() {
return Err("Attempting to reset to block with pruned state".into())
} else if num == 0 {
return Err("invalid number of blocks to reset".into())
}
let (blocks_to_delete, best_block_hash) = self.chain.read()
.block_headers_from_best_block(num)
.ok_or("Attempted to reset past genesis block")?;
let mut blocks_to_delete = Vec::with_capacity(num as usize);
let mut best_block_hash = self.chain.read().best_block_hash();
let mut batch = DBTransaction::with_capacity(blocks_to_delete.len());
let mut db_transaction = DBTransaction::with_capacity((num + 1) as usize);
for _ in 0..num {
let current_header = self.chain.read().block_header_data(&best_block_hash)
.expect("best_block_hash was fetched from db; block_header_data should exist in db; qed");
best_block_hash = current_header.parent_hash();
for hash in &blocks_to_delete {
db_transaction.delete(::db::COL_HEADERS, &hash.hash());
db_transaction.delete(::db::COL_BODIES, &hash.hash());
db_transaction.delete(::db::COL_EXTRA, &hash.hash());
let (number, hash) = (current_header.number(), current_header.hash());
batch.delete(::db::COL_HEADERS, &hash);
batch.delete(::db::COL_BODIES, &hash);
Writable::delete::<BlockDetails, H264>
(&mut batch, ::db::COL_EXTRA, &hash);
Writable::delete::<H256, BlockNumberKey>
(&mut db_transaction, ::db::COL_EXTRA, &hash.number());
(&mut batch, ::db::COL_EXTRA, &number);
blocks_to_delete.push((number, hash));
}
let hashes = blocks_to_delete.iter().map(|(_, hash)| hash).collect::<Vec<_>>();
info!("Deleting block hashes {}",
Colour::Red
.bold()
.paint(format!("{:#?}", hashes))
);
let mut best_block_details = Readable::read::<BlockDetails, H264>(
&**self.db.read().key_value(),
::db::COL_EXTRA,
&best_block_hash
).expect("block was previously imported; best_block_details should exist; qed");
let (_, last_hash) = blocks_to_delete.last()
.expect("num is > 0; blocks_to_delete can't be empty; qed");
// remove the last block as a child so that it can be re-imported
// ethcore/blockchain/src/blockchain.rs/Blockchain::is_known_child()
best_block_details.children.retain(|h| *h != *last_hash);
batch.write(
::db::COL_EXTRA,
&best_block_hash,
&best_block_details
);
// update the new best block hash
db_transaction.put(::db::COL_EXTRA, b"best", &*best_block_hash);
batch.put(::db::COL_EXTRA, b"best", &best_block_hash);
self.db.read()
.key_value()
.write(db_transaction)
.map_err(|err| format!("could not complete reset operation; io error occured: {}", err))?;
let hashes = blocks_to_delete.iter().map(|b| b.hash()).collect::<Vec<_>>();
info!("Deleting block hashes {}",
Colour::Red
.bold()
.paint(format!("{:#?}", hashes))
);
.write(batch)
.map_err(|err| format!("could not delete blocks; io error occurred: {}", err))?;
info!("New best block hash {}", Colour::Green.bold().paint(format!("{:?}", best_block_hash)));
@@ -1578,22 +1593,27 @@ impl Call for Client {
let schedule = machine.schedule(env_info.number);
Executive::new(&mut clone, &env_info, &machine, &schedule)
.transact_virtual(&tx, options())
.ok()
.map(|r| r.exception.is_none())
};
let cond = |gas| exec(gas).unwrap_or(false);
let cond = |gas| {
exec(gas)
.ok()
.map_or(false, |r| r.exception.is_none())
};
if !cond(upper) {
upper = max_upper;
match exec(upper) {
Some(false) => return Err(CallError::Exceptional),
None => {
Ok(v) => {
if let Some(exception) = v.exception {
return Err(CallError::Exceptional(exception))
}
},
Err(_e) => {
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();
@@ -1926,7 +1946,7 @@ impl BlockChainClient for Client {
}
fn find_uncles(&self, hash: &H256) -> Option<Vec<H256>> {
self.chain.read().find_uncle_hashes(hash, self.engine.maximum_uncle_age())
self.chain.read().find_uncle_hashes(hash, MAX_UNCLE_AGE)
}
fn state_data(&self, hash: &H256) -> Option<Bytes> {
@@ -2159,10 +2179,14 @@ impl BlockChainClient for Client {
fn transact_contract(&self, address: Address, data: Bytes) -> Result<(), transaction::Error> {
let authoring_params = self.importer.miner.authoring_params();
let service_transaction_checker = ServiceTransactionChecker::default();
let gas_price = match service_transaction_checker.check_address(self, authoring_params.author) {
Ok(true) => U256::zero(),
_ => self.importer.miner.sensible_gas_price(),
let service_transaction_checker = self.importer.miner.service_transaction_checker();
let gas_price = if let Some(checker) = service_transaction_checker {
match checker.check_address(self, authoring_params.author) {
Ok(true) => U256::zero(),
_ => self.importer.miner.sensible_gas_price(),
}
} else {
self.importer.miner.sensible_gas_price()
};
let transaction = transaction::Transaction {
nonce: self.latest_nonce(&authoring_params.author),
@@ -2284,24 +2308,24 @@ impl ReopenBlock for Client {
fn reopen_block(&self, block: ClosedBlock) -> OpenBlock {
let engine = &*self.engine;
let mut block = block.reopen(engine);
let max_uncles = engine.maximum_uncle_count(block.header().number());
if block.uncles().len() < max_uncles {
let max_uncles = engine.maximum_uncle_count(block.header.number());
if block.uncles.len() < max_uncles {
let chain = self.chain.read();
let h = chain.best_block_hash();
// Add new uncles
let uncles = chain
.find_uncle_hashes(&h, engine.maximum_uncle_age())
.find_uncle_hashes(&h, MAX_UNCLE_AGE)
.unwrap_or_else(Vec::new);
for h in uncles {
if !block.uncles().iter().any(|header| header.hash() == h) {
if !block.uncles.iter().any(|header| header.hash() == h) {
let uncle = chain.block_header_data(&h).expect("find_uncle_hashes only returns hashes for existing headers; qed");
let uncle = uncle.decode().expect("decoding failure");
block.push_uncle(uncle).expect("pushing up to maximum_uncle_count;
push_uncle is not ok only if more than maximum_uncle_count is pushed;
so all push_uncle are Ok;
qed");
if block.uncles().len() >= max_uncles { break }
if block.uncles.len() >= max_uncles { break }
}
}
@@ -2329,15 +2353,15 @@ impl PrepareOpenBlock for Client {
gas_range_target,
extra_data,
is_epoch_begin,
&mut chain.ancestry_with_metadata_iter(best_header.hash()),
chain.ancestry_with_metadata_iter(best_header.hash()),
)?;
// Add uncles
chain
.find_uncle_headers(&h, engine.maximum_uncle_age())
.find_uncle_headers(&h, MAX_UNCLE_AGE)
.unwrap_or_else(Vec::new)
.into_iter()
.take(engine.maximum_uncle_count(open_block.header().number()))
.take(engine.maximum_uncle_count(open_block.header.number()))
.foreach(|h| {
open_block.push_uncle(h.decode().expect("decoding failure")).expect("pushing maximum_uncle_count;
open_block was just created;
@@ -2362,7 +2386,7 @@ impl ImportSealedBlock for Client {
fn import_sealed_block(&self, block: SealedBlock) -> EthcoreResult<H256> {
let start = Instant::now();
let raw = block.rlp_bytes();
let header = block.header().clone();
let header = block.header.clone();
let hash = header.hash();
self.notify(|n| n.block_pre_import(&raw, &hash, header.difficulty()));
@@ -2385,8 +2409,8 @@ impl ImportSealedBlock for Client {
let pending = self.importer.check_epoch_end_signal(
&header,
&block_data,
block.receipts(),
block.state().db(),
&block.receipts,
block.state.db(),
self
)?;
let route = self.importer.commit_block(
@@ -2523,7 +2547,11 @@ impl SnapshotClient for Client {}
impl Drop for Client {
fn drop(&mut self) {
self.engine.stop();
if let Some(c) = Arc::get_mut(&mut self.engine) {
c.stop()
} else {
warn!(target: "shutdown", "unable to get mut ref for engine for shutdown.");
}
}
}

View File

@@ -241,16 +241,17 @@ impl<'a> EvmTestClient<'a> {
transaction: transaction::SignedTransaction,
tracer: T,
vm_tracer: V,
) -> TransactResult<T::Output, V::Output> {
) -> std::result::Result<TransactSuccess<T::Output, V::Output>, TransactErr> {
let initial_gas = transaction.gas;
// Verify transaction
let is_ok = transaction.verify_basic(true, None, false);
if let Err(error) = is_ok {
return TransactResult::Err {
state_root: *self.state.root(),
error: error.into(),
end_state: (self.dump_state)(&self.state),
};
return Err(
TransactErr{
state_root: *self.state.root(),
error: error.into(),
end_state: (self.dump_state)(&self.state),
});
}
// Apply transaction
@@ -283,7 +284,7 @@ impl<'a> EvmTestClient<'a> {
match result {
Ok(result) => {
TransactResult::Ok {
Ok(TransactSuccess {
state_root,
gas_left: initial_gas - result.receipt.gas_used,
outcome: result.receipt.outcome,
@@ -298,47 +299,48 @@ impl<'a> EvmTestClient<'a> {
},
end_state,
}
},
Err(error) => TransactResult::Err {
)},
Err(error) => Err(TransactErr {
state_root,
error,
end_state,
},
}),
}
}
}
/// A result of applying transaction to the state.
#[derive(Debug)]
pub enum TransactResult<T, V> {
/// Successful execution
Ok {
/// State root
state_root: H256,
/// Amount of gas left
gas_left: U256,
/// Output
output: Vec<u8>,
/// Traces
trace: Vec<T>,
/// VM Traces
vm_trace: Option<V>,
/// Created contract address (if any)
contract_address: Option<H160>,
/// Generated logs
logs: Vec<log_entry::LogEntry>,
/// outcome
outcome: receipt::TransactionOutcome,
/// end state if needed
end_state: Option<pod_state::PodState>,
},
/// Transaction failed to run
Err {
/// State root
state_root: H256,
/// Execution error
error: ::error::Error,
/// end state if needed
end_state: Option<pod_state::PodState>,
},
/// To be returned inside a std::result::Result::Ok after a successful
/// transaction completed.
#[allow(dead_code)]
pub struct TransactSuccess<T, V> {
/// State root
pub state_root: H256,
/// Amount of gas left
pub gas_left: U256,
/// Output
pub output: Vec<u8>,
/// Traces
pub trace: Vec<T>,
/// VM Traces
pub vm_trace: Option<V>,
/// Created contract address (if any)
pub contract_address: Option<H160>,
/// Generated logs
pub logs: Vec<log_entry::LogEntry>,
/// outcome
pub outcome: receipt::TransactionOutcome,
/// end state if needed
pub end_state: Option<pod_state::PodState>,
}
/// To be returned inside a std::result::Result::Err after a failed
/// transaction.
#[allow(dead_code)]
pub struct TransactErr {
/// State root
pub state_root: H256,
/// Execution error
pub error: ::error::Error,
/// end state if needed
pub end_state: Option<pod_state::PodState>,
}

View File

@@ -30,7 +30,7 @@ mod trace;
pub use self::client::*;
pub use self::config::{Mode, ClientConfig, DatabaseCompactionProfile, BlockChainConfig, VMType};
#[cfg(any(test, feature = "test-helpers"))]
pub use self::evm_test_client::{EvmTestClient, EvmTestError, TransactResult};
pub use self::evm_test_client::{EvmTestClient, EvmTestError, TransactErr, TransactSuccess};
pub use self::io_message::ClientIoMessage;
#[cfg(any(test, feature = "test-helpers"))]
pub use self::test_client::{TestBlockChainClient, EachBlockWith};

View File

@@ -416,7 +416,7 @@ impl PrepareOpenBlock for TestBlockChainClient {
gas_range_target,
extra_data,
false,
&mut Vec::new().into_iter(),
None,
)?;
// TODO [todr] Override timestamp for predictability
open_block.set_timestamp(*self.latest_block_timestamp.read());

View File

@@ -515,15 +515,19 @@ fn header_expected_seal_fields(header: &Header, empty_steps_transition: u64) ->
}
fn header_step(header: &Header, empty_steps_transition: u64) -> Result<u64, ::rlp::DecoderError> {
let expected_seal_fields = header_expected_seal_fields(header, empty_steps_transition);
Rlp::new(&header.seal().get(0).expect(
&format!("was either checked with verify_block_basic or is genesis; has {} fields; qed (Make sure the spec file has a correct genesis seal)", expected_seal_fields))).as_val()
Rlp::new(&header.seal().get(0).unwrap_or_else(||
panic!("was either checked with verify_block_basic or is genesis; has {} fields; qed (Make sure the spec
file has a correct genesis seal)", header_expected_seal_fields(header, empty_steps_transition))
))
.as_val()
}
fn header_signature(header: &Header, empty_steps_transition: u64) -> Result<Signature, ::rlp::DecoderError> {
let expected_seal_fields = header_expected_seal_fields(header, empty_steps_transition);
Rlp::new(&header.seal().get(1).expect(
&format!("was checked with verify_block_basic; has {} fields; qed", expected_seal_fields))).as_val::<H520>().map(Into::into)
Rlp::new(&header.seal().get(1).unwrap_or_else(||
panic!("was checked with verify_block_basic; has {} fields; qed",
header_expected_seal_fields(header, empty_steps_transition))
))
.as_val::<H520>().map(Into::into)
}
// extracts the raw empty steps vec from the header seal. should only be called when there are 3 fields in the seal
@@ -945,8 +949,12 @@ impl Engine<EthereumMachine> for AuthorityRound {
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());
let step = header_step(header, self.empty_steps_transition).as_ref()
.map(ToString::to_string)
.unwrap_or_default();
let signature = header_signature(header, self.empty_steps_transition).as_ref()
.map(ToString::to_string)
.unwrap_or_default();
let mut info = map![
"step".into() => step,
@@ -1033,7 +1041,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
return Seal::None;
}
let header = block.header();
let header = &block.header;
let parent_step = header_step(parent, self.empty_steps_transition)
.expect("Header has been verified; qed");
@@ -1079,7 +1087,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
// `EmptyStep(step, parent_hash)` message. If we exceed the maximum amount of `empty_step` rounds we proceed
// with the seal.
if header.number() >= self.empty_steps_transition &&
block.transactions().is_empty() &&
block.transactions.is_empty() &&
empty_steps.len() < self.maximum_empty_steps {
if self.step.can_propose.compare_and_swap(true, false, AtomicOrdering::SeqCst) {
@@ -1149,7 +1157,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
if self.immediate_transitions || !epoch_begin { return Ok(()) }
// genesis is never a new block, but might as well check.
let header = block.header().clone();
let header = block.header.clone();
let first = header.number() == 0;
let mut call = |to, data| {
@@ -1169,8 +1177,8 @@ impl Engine<EthereumMachine> for AuthorityRound {
/// Apply the block reward on finalisation of the block.
fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> {
let mut beneficiaries = Vec::new();
if block.header().number() >= self.empty_steps_transition {
let empty_steps = if block.header().seal().is_empty() {
if block.header.number() >= self.empty_steps_transition {
let empty_steps = if block.header.seal().is_empty() {
// this is a new block, calculate rewards based on the empty steps messages we have accumulated
let client = match self.client.read().as_ref().and_then(|weak| weak.upgrade()) {
Some(client) => client,
@@ -1180,7 +1188,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
},
};
let parent = client.block_header(::client::BlockId::Hash(*block.header().parent_hash()))
let parent = client.block_header(::client::BlockId::Hash(*block.header.parent_hash()))
.expect("hash is from parent; parent header must exist; qed")
.decode()?;
@@ -1189,7 +1197,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
self.empty_steps(parent_step.into(), current_step.into(), parent.hash())
} else {
// we're verifying a block, extract empty steps from the seal
header_empty_steps(block.header())?
header_empty_steps(&block.header)?
};
for empty_step in empty_steps {
@@ -1198,11 +1206,11 @@ impl Engine<EthereumMachine> for AuthorityRound {
}
}
let author = *block.header().author();
let author = *block.header.author();
beneficiaries.push((author, RewardKind::Author));
let rewards: Vec<_> = match self.block_reward_contract {
Some(ref c) if block.header().number() >= self.block_reward_contract_transition => {
Some(ref c) if block.header.number() >= self.block_reward_contract_transition => {
let mut call = super::default_system_or_code_call(&self.machine, block);
let rewards = c.reward(&beneficiaries, &mut call)?;
@@ -1631,23 +1639,23 @@ mod tests {
let db1 = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap();
let db2 = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, None).unwrap();
let b1 = b1.close_and_lock().unwrap();
let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes, addr2, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes, addr2, (3141562.into(), 31415620.into()), vec![], false, None).unwrap();
let b2 = b2.close_and_lock().unwrap();
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
if let Seal::Regular(seal) = engine.generate_seal(b1.block(), &genesis_header) {
if let Seal::Regular(seal) = engine.generate_seal(&b1, &genesis_header) {
assert!(b1.clone().try_seal(engine, seal).is_ok());
// Second proposal is forbidden.
assert!(engine.generate_seal(b1.block(), &genesis_header) == Seal::None);
assert!(engine.generate_seal(&b1, &genesis_header) == Seal::None);
}
engine.set_signer(Box::new((tap, addr2, "2".into())));
if let Seal::Regular(seal) = engine.generate_seal(b2.block(), &genesis_header) {
if let Seal::Regular(seal) = engine.generate_seal(&b2, &genesis_header) {
assert!(b2.clone().try_seal(engine, seal).is_ok());
// Second proposal is forbidden.
assert!(engine.generate_seal(b2.block(), &genesis_header) == Seal::None);
assert!(engine.generate_seal(&b2, &genesis_header) == Seal::None);
}
}
@@ -1665,19 +1673,19 @@ mod tests {
let db2 = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, None).unwrap();
let b1 = b1.close_and_lock().unwrap();
let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes, addr2, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes, addr2, (3141562.into(), 31415620.into()), vec![], false, None).unwrap();
let b2 = b2.close_and_lock().unwrap();
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
match engine.generate_seal(b1.block(), &genesis_header) {
match engine.generate_seal(&b1, &genesis_header) {
Seal::None | Seal::Proposal(_) => panic!("wrong seal"),
Seal::Regular(_) => {
engine.step();
engine.set_signer(Box::new((tap.clone(), addr2, "0".into())));
match engine.generate_seal(b2.block(), &genesis_header) {
match engine.generate_seal(&b2, &genesis_header) {
Seal::Regular(_) | Seal::Proposal(_) => panic!("sealed despite wrong difficulty"),
Seal::None => {}
}
@@ -1901,11 +1909,11 @@ mod tests {
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, None).unwrap();
let b1 = b1.close_and_lock().unwrap();
// the block is empty so we don't seal and instead broadcast an empty step message
assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None);
assert_eq!(engine.generate_seal(&b1, &genesis_header), Seal::None);
// spec starts with step 2
let empty_step_rlp = encode(&empty_step(engine, 2, &genesis_header.hash()));
@@ -1915,7 +1923,7 @@ mod tests {
let len = notify.messages.read().len();
// make sure that we don't generate empty step for the second time
assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None);
assert_eq!(engine.generate_seal(&b1, &genesis_header), Seal::None);
assert_eq!(len, notify.messages.read().len());
}
@@ -1939,16 +1947,16 @@ mod tests {
engine.register_client(Arc::downgrade(&client) as _);
// step 2
let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, None).unwrap();
let b1 = b1.close_and_lock().unwrap();
// since the block is empty it isn't sealed and we generate empty steps
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None);
assert_eq!(engine.generate_seal(&b1, &genesis_header), Seal::None);
engine.step();
// step 3
let mut b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr2, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
let mut b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr2, (3141562.into(), 31415620.into()), vec![], false, None).unwrap();
b2.push_transaction(Transaction {
action: Action::Create,
nonce: U256::from(0),
@@ -1961,7 +1969,7 @@ mod tests {
// we will now seal a block with 1tx and include the accumulated empty step message
engine.set_signer(Box::new((tap.clone(), addr2, "0".into())));
if let Seal::Regular(seal) = engine.generate_seal(b2.block(), &genesis_header) {
if let Seal::Regular(seal) = engine.generate_seal(&b2, &genesis_header) {
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
let empty_step2 = sealed_empty_step(engine, 2, &genesis_header.hash());
let empty_steps = ::rlp::encode_list(&vec![empty_step2]);
@@ -1992,28 +2000,28 @@ mod tests {
engine.register_client(Arc::downgrade(&client) as _);
// step 2
let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, None).unwrap();
let b1 = b1.close_and_lock().unwrap();
// since the block is empty it isn't sealed and we generate empty steps
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None);
assert_eq!(engine.generate_seal(&b1, &genesis_header), Seal::None);
engine.step();
// step 3
let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr2, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr2, (3141562.into(), 31415620.into()), vec![], false, None).unwrap();
let b2 = b2.close_and_lock().unwrap();
engine.set_signer(Box::new((tap.clone(), addr2, "0".into())));
assert_eq!(engine.generate_seal(b2.block(), &genesis_header), Seal::None);
assert_eq!(engine.generate_seal(&b2, &genesis_header), Seal::None);
engine.step();
// step 4
// the spec sets the maximum_empty_steps to 2 so we will now seal an empty block and include the empty step messages
let b3 = OpenBlock::new(engine, Default::default(), false, db3, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
let b3 = OpenBlock::new(engine, Default::default(), false, db3, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, None).unwrap();
let b3 = b3.close_and_lock().unwrap();
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
if let Seal::Regular(seal) = engine.generate_seal(b3.block(), &genesis_header) {
if let Seal::Regular(seal) = engine.generate_seal(&b3, &genesis_header) {
let empty_step2 = sealed_empty_step(engine, 2, &genesis_header.hash());
engine.set_signer(Box::new((tap.clone(), addr2, "0".into())));
let empty_step3 = sealed_empty_step(engine, 3, &genesis_header.hash());
@@ -2042,24 +2050,24 @@ mod tests {
engine.register_client(Arc::downgrade(&client) as _);
// step 2
let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, None).unwrap();
let b1 = b1.close_and_lock().unwrap();
// since the block is empty it isn't sealed and we generate empty steps
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None);
assert_eq!(engine.generate_seal(&b1, &genesis_header), Seal::None);
engine.step();
// step 3
// the signer of the accumulated empty step message should be rewarded
let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
let addr1_balance = b2.block().state().balance(&addr1).unwrap();
let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, None).unwrap();
let addr1_balance = b2.state.balance(&addr1).unwrap();
// after closing the block `addr1` should be reward twice, one for the included empty step message and another for block creation
let b2 = b2.close_and_lock().unwrap();
// the spec sets the block reward to 10
assert_eq!(b2.block().state().balance(&addr1).unwrap(), addr1_balance + (10 * 2))
assert_eq!(b2.state.balance(&addr1).unwrap(), addr1_balance + (10 * 2))
}
#[test]
@@ -2152,13 +2160,13 @@ mod tests {
(3141562.into(), 31415620.into()),
vec![],
false,
&mut Vec::new().into_iter(),
None,
).unwrap();
let b1 = b1.close_and_lock().unwrap();
// since the block is empty it isn't sealed and we generate empty steps
engine.set_signer(Box::new((tap.clone(), addr1, "1".into())));
assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None);
assert_eq!(engine.generate_seal(&b1, &genesis_header), Seal::None);
engine.step();
// step 3
@@ -2174,9 +2182,9 @@ mod tests {
(3141562.into(), 31415620.into()),
vec![],
false,
&mut Vec::new().into_iter(),
None,
).unwrap();
let addr1_balance = b2.block().state().balance(&addr1).unwrap();
let addr1_balance = b2.state.balance(&addr1).unwrap();
// after closing the block `addr1` should be reward twice, one for the included empty step
// message and another for block creation
@@ -2184,7 +2192,7 @@ mod tests {
// the contract rewards (1000 + kind) for each benefactor/reward kind
assert_eq!(
b2.block().state().balance(&addr1).unwrap(),
b2.state.balance(&addr1).unwrap(),
addr1_balance + (1000 + 0) + (1000 + 2),
)
}

View File

@@ -104,7 +104,7 @@ impl Engine<EthereumMachine> for BasicAuthority {
/// Attempt to seal the block internally.
fn generate_seal(&self, block: &ExecutedBlock, _parent: &Header) -> Seal {
let header = block.header();
let header = &block.header;
let author = header.author();
if self.validators.contains(header.parent_hash(), author) {
// account should be pernamently unlocked, otherwise sealing will fail
@@ -264,9 +264,9 @@ mod tests {
let genesis_header = spec.genesis_header();
let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![], false, None).unwrap();
let b = b.close_and_lock().unwrap();
if let Seal::Regular(seal) = engine.generate_seal(b.block(), &genesis_header) {
if let Seal::Regular(seal) = engine.generate_seal(&b, &genesis_header) {
assert!(b.try_seal(engine, seal).is_ok());
}
}

View File

@@ -24,11 +24,12 @@ use ethereum_types::{H160, Address, U256};
use std::sync::Arc;
use hash::keccak;
use error::Error;
use machine::WithRewards;
use parity_machine::Machine;
use machine::Machine;
use trace;
use types::BlockNumber;
use super::{SystemOrCodeCall, SystemOrCodeCallKind};
use trace::{Tracer, ExecutiveTracer, Tracing};
use block::ExecutedBlock;
use_contract!(block_reward_contract, "res/contracts/block_reward.json");
@@ -152,17 +153,26 @@ impl BlockRewardContract {
/// Applies the given block rewards, i.e. adds the given balance to each beneficiary' address.
/// If tracing is enabled the operations are recorded.
pub fn apply_block_rewards<M: Machine + WithRewards>(
pub fn apply_block_rewards<M: Machine>(
rewards: &[(Address, RewardKind, U256)],
block: &mut M::LiveBlock,
block: &mut ExecutedBlock,
machine: &M,
) -> Result<(), M::Error> {
for &(ref author, _, ref block_reward) in rewards {
machine.add_balance(block, author, block_reward)?;
}
let rewards: Vec<_> = rewards.into_iter().map(|&(a, k, r)| (a, k.into(), r)).collect();
machine.note_rewards(block, &rewards)
if let Tracing::Enabled(ref mut traces) = *block.traces_mut() {
let mut tracer = ExecutiveTracer::default();
for &(address, reward_kind, amount) in rewards {
tracer.trace_reward(address, amount, reward_kind.into());
}
traces.push(tracer.drain().into());
}
Ok(())
}
#[cfg(test)]

View File

@@ -0,0 +1,369 @@
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.
// Parity Ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use std::collections::{HashMap, BTreeSet, VecDeque};
use std::fmt;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use engines::EngineError;
use engines::clique::util::{extract_signers, recover_creator};
use engines::clique::{VoteType, DIFF_INTURN, DIFF_NOTURN, NULL_AUTHOR, SIGNING_DELAY_NOTURN_MS};
use error::{Error, BlockError};
use ethereum_types::{Address, H64};
use rand::Rng;
use types::BlockNumber;
use types::header::Header;
use unexpected::Mismatch;
#[cfg(not(feature = "time_checked_add"))]
use time_utils::CheckedSystemTime;
/// Type that keeps track of the state for a given vote
// Votes that go against the proposal aren't counted since it's equivalent to not voting
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub struct VoteState {
kind: VoteType,
votes: u64,
}
/// Type that represent a vote
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub struct Vote {
block_number: BlockNumber,
beneficiary: Address,
kind: VoteType,
signer: Address,
reverted: bool,
}
/// Type that represent a pending vote
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd)]
pub struct PendingVote {
signer: Address,
beneficiary: Address,
}
/// Clique state for each block.
#[cfg(not(test))]
#[derive(Clone, Debug, Default)]
pub struct CliqueBlockState {
/// Current votes for a beneficiary
votes: HashMap<PendingVote, VoteState>,
/// A list of all votes for the given epoch
votes_history: Vec<Vote>,
/// a list of all valid signer, sorted by ascending order.
signers: BTreeSet<Address>,
/// a deque of recent signer, new entry should be pushed front, apply() modifies this.
recent_signers: VecDeque<Address>,
/// inturn signing should wait until this time
pub next_timestamp_inturn: Option<SystemTime>,
/// noturn signing should wait until this time
pub next_timestamp_noturn: Option<SystemTime>,
}
#[cfg(test)]
#[derive(Clone, Debug, Default)]
pub struct CliqueBlockState {
/// All recorded votes for a given signer, `Vec<PendingVote>` is a stack of votes
pub votes: HashMap<PendingVote, VoteState>,
/// A list of all votes for the given epoch
pub votes_history: Vec<Vote>,
/// a list of all valid signer, sorted by ascending order.
pub signers: BTreeSet<Address>,
/// a deque of recent signer, new entry should be pushed front, apply() modifies this.
pub recent_signers: VecDeque<Address>,
/// inturn signing should wait until this time
pub next_timestamp_inturn: Option<SystemTime>,
/// noturn signing should wait until this time
pub next_timestamp_noturn: Option<SystemTime>,
}
impl fmt::Display for CliqueBlockState {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let signers: Vec<String> = self.signers.iter()
.map(|s|
format!("{} {:?}",
s,
self.votes.iter().map(|(v, s)| format!("[beneficiary {}, votes: {}]", v.beneficiary, s.votes))
.collect::<Vec<_>>()
)
)
.collect();
let recent_signers: Vec<String> = self.recent_signers.iter().map(|s| format!("{}", s)).collect();
let num_votes = self.votes_history.len();
let add_votes = self.votes_history.iter().filter(|v| v.kind == VoteType::Add).count();
let rm_votes = self.votes_history.iter().filter(|v| v.kind == VoteType::Remove).count();
let reverted_votes = self.votes_history.iter().filter(|v| v.reverted).count();
write!(f,
"Votes {{ \n signers: {:?} \n recent_signers: {:?} \n number of votes: {} \n number of add votes {}
\r number of remove votes {} \n number of reverted votes: {}}}",
signers, recent_signers, num_votes, add_votes, rm_votes, reverted_votes)
}
}
impl CliqueBlockState {
/// Create new state with given information, this is used creating new state from Checkpoint block.
pub fn new(signers: BTreeSet<Address>) -> Self {
CliqueBlockState {
signers,
..Default::default()
}
}
// see https://github.com/ethereum/go-ethereum/blob/master/consensus/clique/clique.go#L474
fn verify(&self, header: &Header) -> Result<Address, Error> {
let creator = recover_creator(header)?.clone();
// The signer is not authorized
if !self.signers.contains(&creator) {
trace!(target: "engine", "current state: {}", self);
Err(EngineError::NotAuthorized(creator))?
}
// The signer has signed a block too recently
if self.recent_signers.contains(&creator) {
trace!(target: "engine", "current state: {}", self);
Err(EngineError::CliqueTooRecentlySigned(creator))?
}
// Wrong difficulty
let inturn = self.is_inturn(header.number(), &creator);
if inturn && *header.difficulty() != DIFF_INTURN {
Err(BlockError::InvalidDifficulty(Mismatch {
expected: DIFF_INTURN,
found: *header.difficulty(),
}))?
}
if !inturn && *header.difficulty() != DIFF_NOTURN {
Err(BlockError::InvalidDifficulty(Mismatch {
expected: DIFF_NOTURN,
found: *header.difficulty(),
}))?
}
Ok(creator)
}
/// Verify and apply a new header to current state
pub fn apply(&mut self, header: &Header, is_checkpoint: bool) -> Result<Address, Error> {
let creator = self.verify(header)?;
self.recent_signers.push_front(creator);
self.rotate_recent_signers();
if is_checkpoint {
// checkpoint block should not affect previous tallying, so we check that.
let signers = extract_signers(header)?;
if self.signers != signers {
let invalid_signers: Vec<String> = signers.into_iter()
.filter(|s| !self.signers.contains(s))
.map(|s| format!("{}", s))
.collect();
Err(EngineError::CliqueFaultyRecoveredSigners(invalid_signers))?
};
// TODO(niklasad1): I'm not sure if we should shrink here because it is likely that next epoch
// will need some memory and might be better for allocation algorithm to decide whether to shrink or not
// (typically doubles or halves the allocted memory when necessary)
self.votes.clear();
self.votes_history.clear();
self.votes.shrink_to_fit();
self.votes_history.shrink_to_fit();
}
// Contains vote
if *header.author() != NULL_AUTHOR {
let decoded_seal = header.decode_seal::<Vec<_>>()?;
if decoded_seal.len() != 2 {
Err(BlockError::InvalidSealArity(Mismatch { expected: 2, found: decoded_seal.len() }))?
}
let nonce: H64 = decoded_seal[1].into();
self.update_signers_on_vote(VoteType::from_nonce(nonce)?, creator, *header.author(), header.number())?;
}
Ok(creator)
}
fn update_signers_on_vote(
&mut self,
kind: VoteType,
signer: Address,
beneficiary: Address,
block_number: u64
) -> Result<(), Error> {
trace!(target: "engine", "Attempt vote {:?} {:?}", kind, beneficiary);
let pending_vote = PendingVote { signer, beneficiary };
let reverted = if self.is_valid_vote(&beneficiary, kind) {
self.add_vote(pending_vote, kind)
} else {
// This case only happens if a `signer` wants to revert their previous vote
// (does nothing if no previous vote was found)
self.revert_vote(pending_vote)
};
// Add all votes to the history
self.votes_history.push(
Vote {
block_number,
beneficiary,
kind,
signer,
reverted,
});
// If no vote was found for the beneficiary return `early` but don't propogate an error
let (votes, vote_kind) = match self.get_current_votes_and_kind(beneficiary) {
Some((v, k)) => (v, k),
None => return Ok(()),
};
let threshold = self.signers.len() / 2;
debug!(target: "engine", "{}/{} votes to have consensus", votes, threshold + 1);
trace!(target: "engine", "votes: {:?}", votes);
if votes > threshold {
match vote_kind {
VoteType::Add => {
if self.signers.insert(beneficiary) {
debug!(target: "engine", "added new signer: {}", beneficiary);
}
}
VoteType::Remove => {
if self.signers.remove(&beneficiary) {
debug!(target: "engine", "removed signer: {}", beneficiary);
}
}
}
self.rotate_recent_signers();
self.remove_all_votes_from(beneficiary);
}
Ok(())
}
/// Calculate the next timestamp for `inturn` and `noturn` fails if any of them can't be represented as
/// `SystemTime`
// TODO(niklasad1): refactor this method to be in constructor of `CliqueBlockState` instead.
// This is a quite bad API because we must mutate both variables even when already `inturn` fails
// That's why we can't return early and must have the `if-else` in the end
pub fn calc_next_timestamp(&mut self, timestamp: u64, period: u64) -> Result<(), Error> {
let inturn = UNIX_EPOCH.checked_add(Duration::from_secs(timestamp.saturating_add(period)));
self.next_timestamp_inturn = inturn;
let delay = Duration::from_millis(
rand::thread_rng().gen_range(0u64, (self.signers.len() as u64 / 2 + 1) * SIGNING_DELAY_NOTURN_MS));
self.next_timestamp_noturn = inturn.map(|inturn| {
inturn + delay
});
if self.next_timestamp_inturn.is_some() && self.next_timestamp_noturn.is_some() {
Ok(())
} else {
Err(BlockError::TimestampOverflow)?
}
}
/// Returns true if the block difficulty should be `inturn`
pub fn is_inturn(&self, current_block_number: u64, author: &Address) -> bool {
if let Some(pos) = self.signers.iter().position(|x| *author == *x) {
return current_block_number % self.signers.len() as u64 == pos as u64;
}
false
}
/// Returns whether the signer is authorized to sign a block
pub fn is_authorized(&self, author: &Address) -> bool {
self.signers.contains(author) && !self.recent_signers.contains(author)
}
/// Returns whether it makes sense to cast the specified vote in the
/// current state (e.g. don't try to add an already authorized signer).
pub fn is_valid_vote(&self, address: &Address, vote_type: VoteType) -> bool {
let in_signer = self.signers.contains(address);
match vote_type {
VoteType::Add => !in_signer,
VoteType::Remove => in_signer,
}
}
/// Returns the list of current signers
pub fn signers(&self) -> &BTreeSet<Address> {
&self.signers
}
// Note this method will always return `true` but it is intended for a uniform `API`
fn add_vote(&mut self, pending_vote: PendingVote, kind: VoteType) -> bool {
self.votes.entry(pending_vote)
.and_modify(|state| {
state.votes = state.votes.saturating_add(1);
})
.or_insert_with(|| VoteState { kind, votes: 1 });
true
}
fn revert_vote(&mut self, pending_vote: PendingVote) -> bool {
let mut revert = false;
let mut remove = false;
self.votes.entry(pending_vote).and_modify(|state| {
if state.votes.saturating_sub(1) == 0 {
remove = true;
}
revert = true;
});
if remove {
self.votes.remove(&pending_vote);
}
revert
}
fn get_current_votes_and_kind(&self, beneficiary: Address) -> Option<(usize, VoteType)> {
let kind = self.votes.iter()
.find(|(v, _t)| v.beneficiary == beneficiary)
.map(|(_v, t)| t.kind)?;
let votes = self.votes.keys()
.filter(|vote| vote.beneficiary == beneficiary)
.count();
Some((votes, kind))
}
fn rotate_recent_signers(&mut self) {
if self.recent_signers.len() >= ( self.signers.len() / 2 ) + 1 {
self.recent_signers.pop_back();
}
}
fn remove_all_votes_from(&mut self, beneficiary: Address) {
self.votes = std::mem::replace(&mut self.votes, HashMap::new())
.into_iter()
.filter(|(v, _t)| v.signer != beneficiary && v.beneficiary != beneficiary)
.collect();
}
}

View File

@@ -0,0 +1,776 @@
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.
// Parity Ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
//! Implementation of the Clique PoA Engine.
//!
//! File structure:
//! - mod.rs -> Provides the engine API implementation, with additional block state tracking
//! - block_state.rs -> Records the Clique state for given block.
//! - params.rs -> Contains the parameters for the Clique engine.
//! - step_service.rs -> An event loop to trigger sealing.
//! - util.rs -> Various standalone utility functions.
//! - tests.rs -> Consensus tests as defined in EIP-225.
/// How syncing works:
///
/// 1. Client will call:
/// - `Clique::verify_block_basic()`
/// - `Clique::verify_block_unordered()`
/// - `Clique::verify_block_family()`
/// 2. Using `Clique::state()` we try and retrieve the parent state. If this isn't found
/// we need to back-fill it from the last known checkpoint.
/// 3. Once we have a good state, we can record it using `CliqueBlockState::apply()`.
/// How sealing works:
///
/// 1. Set a signer using `Engine::set_signer()`. If a miner account was set up through
/// a config file or CLI flag `MinerService::set_author()` will eventually set the signer
/// 2. We check that the engine seals internally through `Clique::seals_internally()`
/// Note: This is always true for Clique
/// 3. Calling `Clique::new()` will spawn a `StepService` thread. This thread will call `Engine::step()`
/// periodically. Internally, the Clique `step()` function calls `Client::update_sealing()`, which is
/// what makes and seals a block.
/// 4. `Clique::generate_seal()` will then be called by `miner`. This will return a `Seal` which
/// is either a `Seal::None` or `Seal:Regular`. The following shows how a `Seal` variant is chosen:
/// a. We return `Seal::None` if no signer is available or the signer is not authorized.
/// b. If period == 0 and block has transactions, we return `Seal::Regular`, otherwise return `Seal::None`.
/// c. If we're `INTURN`, wait for at least `period` since last block before trying to seal.
/// d. If we're not `INTURN`, we wait for a random amount of time using the algorithm specified
/// in EIP-225 before trying to seal again.
/// 5. Miner will create new block, in process it will call several engine methods to do following:
/// a. `Clique::open_block_header_timestamp()` must set timestamp correctly.
/// b. `Clique::populate_from_parent()` must set difficulty to correct value.
/// Note: `Clique::populate_from_parent()` is used in both the syncing and sealing code paths.
/// 6. We call `Clique::on_seal_block()` which will allow us to modify the block header during seal generation.
/// 7. Finally, `Clique::verify_local_seal()` is called. After this, the syncing code path will be followed
/// in order to import the new block.
use std::cmp;
use std::collections::HashMap;
use std::collections::VecDeque;
use std::sync::{Arc, Weak};
use std::thread;
use std::time;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use block::ExecutedBlock;
use bytes::Bytes;
use client::{BlockId, EngineClient};
use engines::clique::util::{extract_signers, recover_creator};
use engines::{Engine, EngineError, Seal};
use error::{BlockError, Error};
use ethereum_types::{Address, H64, H160, H256, U256};
use ethkey::Signature;
use hash::KECCAK_EMPTY_LIST_RLP;
use itertools::Itertools;
use lru_cache::LruCache;
use machine::{Call, EthereumMachine};
use parking_lot::RwLock;
use rand::Rng;
use super::signer::EngineSigner;
use unexpected::{Mismatch, OutOfBounds};
use types::BlockNumber;
use types::header::{ExtendedHeader, Header};
#[cfg(not(feature = "time_checked_add"))]
use time_utils::CheckedSystemTime;
use self::block_state::CliqueBlockState;
use self::params::CliqueParams;
use self::step_service::StepService;
mod params;
mod block_state;
mod step_service;
mod util;
// TODO(niklasad1): extract tester types into a separate mod to be shared in the code base
#[cfg(test)]
mod tests;
// Protocol constants
/// Fixed number of extra-data prefix bytes reserved for signer vanity
pub const VANITY_LENGTH: usize = 32;
/// Fixed number of extra-data suffix bytes reserved for signer signature
pub const SIGNATURE_LENGTH: usize = 65;
/// Address length of signer
pub const ADDRESS_LENGTH: usize = 20;
/// Nonce value for DROP vote
pub const NONCE_DROP_VOTE: H64 = H64([0; 8]);
/// Nonce value for AUTH vote
pub const NONCE_AUTH_VOTE: H64 = H64([0xff; 8]);
/// Difficulty for INTURN block
pub const DIFF_INTURN: U256 = U256([2, 0, 0, 0]);
/// Difficulty for NOTURN block
pub const DIFF_NOTURN: U256 = U256([1, 0, 0, 0]);
/// Default empty author field value
pub const NULL_AUTHOR: Address = H160([0x00; 20]);
/// Default empty nonce value
pub const NULL_NONCE: H64 = NONCE_DROP_VOTE;
/// Default value for mixhash
pub const NULL_MIXHASH: H256 = H256([0; 32]);
/// Default value for uncles hash
pub const NULL_UNCLES_HASH: H256 = KECCAK_EMPTY_LIST_RLP;
/// Default noturn block wiggle factor defined in spec.
pub const SIGNING_DELAY_NOTURN_MS: u64 = 500;
/// How many CliqueBlockState to cache in the memory.
pub const STATE_CACHE_NUM: usize = 128;
/// Vote to add or remove the beneficiary
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub enum VoteType {
Add,
Remove,
}
impl VoteType {
/// Try to construct a `Vote` from a nonce
pub fn from_nonce(nonce: H64) -> Result<Self, Error> {
if nonce == NONCE_AUTH_VOTE {
Ok(VoteType::Add)
} else if nonce == NONCE_DROP_VOTE {
Ok(VoteType::Remove)
} else {
Err(EngineError::CliqueInvalidNonce(nonce))?
}
}
/// Get the rlp encoding of the vote
pub fn as_rlp(&self) -> Vec<Vec<u8>> {
match self {
VoteType::Add => vec![rlp::encode(&NULL_MIXHASH), rlp::encode(&NONCE_AUTH_VOTE)],
VoteType::Remove => vec![rlp::encode(&NULL_MIXHASH), rlp::encode(&NONCE_DROP_VOTE)],
}
}
}
/// Clique Engine implementation
// block_state_by_hash -> block state indexed by header hash.
#[cfg(not(test))]
pub struct Clique {
epoch_length: u64,
period: u64,
machine: EthereumMachine,
client: RwLock<Option<Weak<EngineClient>>>,
block_state_by_hash: RwLock<LruCache<H256, CliqueBlockState>>,
proposals: RwLock<HashMap<Address, VoteType>>,
signer: RwLock<Option<Box<EngineSigner>>>,
step_service: Option<Arc<StepService>>,
}
#[cfg(test)]
/// Test version of `CliqueEngine` to make all fields public
pub struct Clique {
pub epoch_length: u64,
pub period: u64,
pub machine: EthereumMachine,
pub client: RwLock<Option<Weak<EngineClient>>>,
pub block_state_by_hash: RwLock<LruCache<H256, CliqueBlockState>>,
pub proposals: RwLock<HashMap<Address, VoteType>>,
pub signer: RwLock<Option<Box<EngineSigner>>>,
pub step_service: Option<Arc<StepService>>,
}
impl Clique {
/// Initialize Clique engine from empty state.
pub fn new(our_params: CliqueParams, machine: EthereumMachine) -> Result<Arc<Self>, Error> {
let mut engine = Clique {
epoch_length: our_params.epoch,
period: our_params.period,
client: Default::default(),
block_state_by_hash: RwLock::new(LruCache::new(STATE_CACHE_NUM)),
proposals: Default::default(),
signer: Default::default(),
machine,
step_service: None,
};
let res = Arc::new(engine);
if our_params.period > 0 {
engine.step_service = Some(StepService::start(Arc::downgrade(&res) as Weak<Engine<_>>));
}
Ok(res)
}
#[cfg(test)]
/// Initialize test variant of `CliqueEngine`,
/// Note we need to `mock` the miner and it is introduced to test block verification to trigger new blocks
/// to mainly test consensus edge cases
pub fn with_test(epoch_length: u64, period: u64) -> Self {
use spec::Spec;
Self {
epoch_length,
period,
client: Default::default(),
block_state_by_hash: RwLock::new(LruCache::new(STATE_CACHE_NUM)),
proposals: Default::default(),
signer: Default::default(),
machine: Spec::new_test_machine(),
step_service: None,
}
}
fn sign_header(&self, header: &Header) -> Result<(Signature, H256), Error> {
match self.signer.read().as_ref() {
None => {
Err(EngineError::RequiresSigner)?
}
Some(signer) => {
let digest = header.hash();
match signer.sign(digest) {
Ok(sig) => Ok((sig, digest)),
Err(e) => Err(EngineError::Custom(e.into()))?,
}
}
}
}
/// Construct an new state from given checkpoint header.
fn new_checkpoint_state(&self, header: &Header) -> Result<CliqueBlockState, Error> {
debug_assert_eq!(header.number() % self.epoch_length, 0);
let mut state = CliqueBlockState::new(
extract_signers(header)?);
// TODO(niklasad1): refactor to perform this check in the `CliqueBlockState` constructor instead
state.calc_next_timestamp(header.timestamp(), self.period)?;
Ok(state)
}
fn state_no_backfill(&self, hash: &H256) -> Option<CliqueBlockState> {
self.block_state_by_hash.write().get_mut(hash).cloned()
}
/// Get `CliqueBlockState` for given header, backfill from last checkpoint if needed.
fn state(&self, header: &Header) -> Result<CliqueBlockState, Error> {
let mut block_state_by_hash = self.block_state_by_hash.write();
if let Some(state) = block_state_by_hash.get_mut(&header.hash()) {
return Ok(state.clone());
}
// If we are looking for an checkpoint block state, we can directly reconstruct it.
if header.number() % self.epoch_length == 0 {
let state = self.new_checkpoint_state(header)?;
block_state_by_hash.insert(header.hash(), state.clone());
return Ok(state);
}
// BlockState is not found in memory, which means we need to reconstruct state from last checkpoint.
match self.client.read().as_ref().and_then(|w| w.upgrade()) {
None => {
return Err(EngineError::RequiresClient)?;
}
Some(c) => {
let last_checkpoint_number = header.number() - header.number() % self.epoch_length as u64;
debug_assert_ne!(last_checkpoint_number, header.number());
// Catching up state, note that we don't really store block state for intermediary blocks,
// for speed.
let backfill_start = time::Instant::now();
trace!(target: "engine",
"Back-filling block state. last_checkpoint_number: {}, target: {}({}).",
last_checkpoint_number, header.number(), header.hash());
let mut chain: &mut VecDeque<Header> = &mut VecDeque::with_capacity(
(header.number() - last_checkpoint_number + 1) as usize);
// Put ourselves in.
chain.push_front(header.clone());
// populate chain to last checkpoint
loop {
let (last_parent_hash, last_num) = {
let l = chain.front().expect("chain has at least one element; qed");
(*l.parent_hash(), l.number())
};
if last_num == last_checkpoint_number + 1 {
break;
}
match c.block_header(BlockId::Hash(last_parent_hash)) {
None => {
return Err(BlockError::UnknownParent(last_parent_hash))?;
}
Some(next) => {
chain.push_front(next.decode()?);
}
}
}
// Get the state for last checkpoint.
let last_checkpoint_hash = *chain.front()
.expect("chain has at least one element; qed")
.parent_hash();
let last_checkpoint_header = match c.block_header(BlockId::Hash(last_checkpoint_hash)) {
None => return Err(EngineError::CliqueMissingCheckpoint(last_checkpoint_hash))?,
Some(header) => header.decode()?,
};
let last_checkpoint_state = match block_state_by_hash.get_mut(&last_checkpoint_hash) {
Some(state) => state.clone(),
None => self.new_checkpoint_state(&last_checkpoint_header)?,
};
block_state_by_hash.insert(last_checkpoint_header.hash(), last_checkpoint_state.clone());
// Backfill!
let mut new_state = last_checkpoint_state.clone();
for item in chain {
new_state.apply(item, false)?;
}
new_state.calc_next_timestamp(header.timestamp(), self.period)?;
block_state_by_hash.insert(header.hash(), new_state.clone());
let elapsed = backfill_start.elapsed();
trace!(target: "engine", "Back-filling succeed, took {} ms.", elapsed.as_millis());
Ok(new_state)
}
}
}
}
impl Engine<EthereumMachine> for Clique {
fn name(&self) -> &str { "Clique" }
fn machine(&self) -> &EthereumMachine { &self.machine }
// Clique use same fields, nonce + mixHash
fn seal_fields(&self, _header: &Header) -> usize { 2 }
fn maximum_uncle_count(&self, _block: BlockNumber) -> usize { 0 }
fn on_new_block(
&self,
_block: &mut ExecutedBlock,
_epoch_begin: bool,
_ancestry: &mut Iterator<Item=ExtendedHeader>,
) -> Result<(), Error> {
Ok(())
}
// Clique has no block reward.
fn on_close_block(&self, _block: &mut ExecutedBlock) -> Result<(), Error> {
Ok(())
}
fn on_seal_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> {
trace!(target: "engine", "on_seal_block");
let header = &mut block.header;
let state = self.state_no_backfill(header.parent_hash())
.ok_or_else(|| BlockError::UnknownParent(*header.parent_hash()))?;
let is_checkpoint = header.number() % self.epoch_length == 0;
header.set_author(NULL_AUTHOR);
// Cast a random Vote if not checkpoint
if !is_checkpoint {
// TODO(niklasad1): this will always be false because `proposals` is never written to
let votes = self.proposals.read().iter()
.filter(|(address, vote_type)| state.is_valid_vote(*address, **vote_type))
.map(|(address, vote_type)| (*address, *vote_type))
.collect_vec();
if !votes.is_empty() {
// Pick a random vote.
let random_vote = rand::thread_rng().gen_range(0 as usize, votes.len());
let (beneficiary, vote_type) = votes[random_vote];
trace!(target: "engine", "Casting vote: beneficiary {}, type {:?} ", beneficiary, vote_type);
header.set_author(beneficiary);
header.set_seal(vote_type.as_rlp());
}
}
// Work on clique seal.
let mut seal: Vec<u8> = Vec::with_capacity(VANITY_LENGTH + SIGNATURE_LENGTH);
// At this point, extra_data should only contain miner vanity.
if header.extra_data().len() != VANITY_LENGTH {
Err(BlockError::ExtraDataOutOfBounds(OutOfBounds {
min: Some(VANITY_LENGTH),
max: Some(VANITY_LENGTH),
found: header.extra_data().len()
}))?;
}
// vanity
{
seal.extend_from_slice(&header.extra_data()[0..VANITY_LENGTH]);
}
// If we are building an checkpoint block, add all signers now.
if is_checkpoint {
seal.reserve(state.signers().len() * 20);
state.signers().iter().foreach(|addr| {
seal.extend_from_slice(&addr[..]);
});
}
header.set_extra_data(seal.clone());
// append signature onto extra_data
let (sig, _msg) = self.sign_header(&header)?;
seal.extend_from_slice(&sig[..]);
header.set_extra_data(seal.clone());
header.compute_hash();
// locally sealed block don't go through valid_block_family(), so we have to record state here.
let mut new_state = state.clone();
new_state.apply(&header, is_checkpoint)?;
new_state.calc_next_timestamp(header.timestamp(), self.period)?;
self.block_state_by_hash.write().insert(header.hash(), new_state);
trace!(target: "engine", "on_seal_block: finished, final header: {:?}", header);
Ok(())
}
/// Clique doesn't require external work to seal, so we always return true here.
fn seals_internally(&self) -> Option<bool> {
Some(true)
}
/// Returns if we are ready to seal, the real sealing (signing extra_data) is actually done in `on_seal_block()`.
fn generate_seal(&self, block: &ExecutedBlock, parent: &Header) -> Seal {
trace!(target: "engine", "tried to generate_seal");
let null_seal = util::null_seal();
if block.header.number() == 0 {
trace!(target: "engine", "attempted to seal genesis block");
return Seal::None;
}
// if sealing period is 0, and not an checkpoint block, refuse to seal
if self.period == 0 {
if block.transactions.is_empty() && block.header.number() % self.epoch_length != 0 {
return Seal::None;
}
return Seal::Regular(null_seal);
}
// Check we actually have authority to seal.
if let Some(author) = self.signer.read().as_ref().map(|x| x.address()) {
// ensure the voting state exists
match self.state(&parent) {
Err(e) => {
warn!(target: "engine", "generate_seal: can't get parent state(number: {}, hash: {}): {} ",
parent.number(), parent.hash(), e);
return Seal::None;
}
Ok(state) => {
// Are we authorized to seal?
if !state.is_authorized(&author) {
trace!(target: "engine", "generate_seal: Not authorized to sign right now.");
// wait for one third of period to try again.
thread::sleep(Duration::from_secs(self.period / 3 + 1));
return Seal::None;
}
let inturn = state.is_inturn(block.header.number(), &author);
let now = SystemTime::now();
let limit = match inturn {
true => state.next_timestamp_inturn.unwrap_or(now),
false => state.next_timestamp_noturn.unwrap_or(now),
};
// Wait for the right moment.
if now < limit {
trace!(target: "engine",
"generate_seal: sleeping to sign: inturn: {}, now: {:?}, to: {:?}.",
inturn, now, limit);
match limit.duration_since(SystemTime::now()) {
Ok(duration) => {
thread::sleep(duration);
},
Err(e) => {
warn!(target:"engine", "generate_seal: unable to sleep, err: {}", e);
return Seal::None;
}
}
}
trace!(target: "engine", "generate_seal: seal ready for block {}, txs: {}.",
block.header.number(), block.transactions.len());
return Seal::Regular(null_seal);
}
}
}
Seal::None
}
fn verify_local_seal(&self, _header: &Header) -> Result<(), Error> { Ok(()) }
fn verify_block_basic(&self, header: &Header) -> Result<(), Error> {
// Largely same as https://github.com/ethereum/go-ethereum/blob/master/consensus/clique/clique.go#L275
// Ignore genesis block.
if header.number() == 0 {
return Ok(());
}
// Don't waste time checking blocks from the future
{
let limit = SystemTime::now().checked_add(Duration::from_secs(self.period))
.ok_or(BlockError::TimestampOverflow)?;
// This should succeed under the contraints that the system clock works
let limit_as_dur = limit.duration_since(UNIX_EPOCH).map_err(|e| {
Box::new(format!("Converting SystemTime to Duration failed: {}", e))
})?;
let hdr = Duration::from_secs(header.timestamp());
if hdr > limit_as_dur {
let found = UNIX_EPOCH.checked_add(hdr).ok_or(BlockError::TimestampOverflow)?;
Err(BlockError::TemporarilyInvalid(OutOfBounds {
min: None,
max: Some(limit),
found,
}))?
}
}
let is_checkpoint = header.number() % self.epoch_length == 0;
if is_checkpoint && *header.author() != NULL_AUTHOR {
return Err(EngineError::CliqueWrongAuthorCheckpoint(Mismatch {
expected: 0.into(),
found: *header.author(),
}))?;
}
let seal_fields = header.decode_seal::<Vec<_>>()?;
if seal_fields.len() != 2 {
Err(BlockError::InvalidSealArity(Mismatch {
expected: 2,
found: seal_fields.len(),
}))?
}
let mixhash: H256 = seal_fields[0].into();
let nonce: H64 = seal_fields[1].into();
// Nonce must be 0x00..0 or 0xff..f
if nonce != NONCE_DROP_VOTE && nonce != NONCE_AUTH_VOTE {
Err(EngineError::CliqueInvalidNonce(nonce))?;
}
if is_checkpoint && nonce != NULL_NONCE {
Err(EngineError::CliqueInvalidNonce(nonce))?;
}
// Ensure that the mix digest is zero as Clique don't have fork protection currently
if mixhash != NULL_MIXHASH {
Err(BlockError::MismatchedH256SealElement(Mismatch {
expected: NULL_MIXHASH,
found: mixhash,
}))?
}
let extra_data_len = header.extra_data().len();
if extra_data_len < VANITY_LENGTH {
Err(EngineError::CliqueMissingVanity)?
}
if extra_data_len < VANITY_LENGTH + SIGNATURE_LENGTH {
Err(EngineError::CliqueMissingSignature)?
}
let signers = extra_data_len - (VANITY_LENGTH + SIGNATURE_LENGTH);
// Checkpoint blocks must at least contain one signer
if is_checkpoint && signers == 0 {
Err(EngineError::CliqueCheckpointNoSigner)?
}
// Addresses must be be divisable by 20
if is_checkpoint && signers % ADDRESS_LENGTH != 0 {
Err(EngineError::CliqueCheckpointInvalidSigners(signers))?
}
// Ensure that the block doesn't contain any uncles which are meaningless in PoA
if *header.uncles_hash() != NULL_UNCLES_HASH {
Err(BlockError::InvalidUnclesHash(Mismatch {
expected: NULL_UNCLES_HASH,
found: *header.uncles_hash(),
}))?
}
// Ensure that the block's difficulty is meaningful (may not be correct at this point)
if *header.difficulty() != DIFF_INTURN && *header.difficulty() != DIFF_NOTURN {
Err(BlockError::DifficultyOutOfBounds(OutOfBounds {
min: Some(DIFF_NOTURN),
max: Some(DIFF_INTURN),
found: *header.difficulty(),
}))?
}
// All basic checks passed, continue to next phase
Ok(())
}
fn verify_block_unordered(&self, _header: &Header) -> Result<(), Error> {
// Nothing to check here.
Ok(())
}
/// Verify block family by looking up parent state (backfill if needed), then try to apply current header.
/// see https://github.com/ethereum/go-ethereum/blob/master/consensus/clique/clique.go#L338
fn verify_block_family(&self, header: &Header, parent: &Header) -> Result<(), Error> {
// Ignore genesis block.
if header.number() == 0 {
return Ok(());
}
// parent sanity check
if parent.hash() != *header.parent_hash() || header.number() != parent.number() + 1 {
Err(BlockError::UnknownParent(parent.hash()))?
}
// Ensure that the block's timestamp isn't too close to it's parent
let limit = parent.timestamp().saturating_add(self.period);
if limit > header.timestamp() {
let max = UNIX_EPOCH.checked_add(Duration::from_secs(header.timestamp()));
let found = UNIX_EPOCH.checked_add(Duration::from_secs(limit))
.ok_or(BlockError::TimestampOverflow)?;
Err(BlockError::InvalidTimestamp(OutOfBounds {
min: None,
max,
found,
}))?
}
// Retrieve the parent state
let parent_state = self.state(&parent)?;
// Try to apply current state, apply() will further check signer and recent signer.
let mut new_state = parent_state.clone();
new_state.apply(header, header.number() % self.epoch_length == 0)?;
new_state.calc_next_timestamp(header.timestamp(), self.period)?;
self.block_state_by_hash.write().insert(header.hash(), new_state);
Ok(())
}
fn genesis_epoch_data(&self, header: &Header, _call: &Call) -> Result<Vec<u8>, String> {
let mut state = self.new_checkpoint_state(header).expect("Unable to parse genesis data.");
state.calc_next_timestamp(header.timestamp(), self.period).map_err(|e| format!("{}", e))?;
self.block_state_by_hash.write().insert(header.hash(), state);
// no proof.
Ok(Vec::new())
}
// Our task here is to set difficulty
fn populate_from_parent(&self, header: &mut Header, parent: &Header) {
// TODO(https://github.com/paritytech/parity-ethereum/issues/10410): this is a horrible hack,
// it is due to the fact that enact and miner both use OpenBlock::new() which will both call
// this function. more refactoring is definitely needed.
if header.extra_data().len() < VANITY_LENGTH + SIGNATURE_LENGTH {
trace!(target: "engine", "populate_from_parent in sealing");
// It's unclear how to prevent creating new blocks unless we are authorized, the best way (and geth does this too)
// it's just to ignore setting an correct difficulty here, we will check authorization in next step in generate_seal anyway.
if let Some(signer) = self.signer.read().as_ref() {
let state = match self.state(&parent) {
Err(e) => {
trace!(target: "engine", "populate_from_parent: Unable to find parent state: {}, ignored.", e);
return;
}
Ok(state) => state,
};
if state.is_authorized(&signer.address()) {
if state.is_inturn(header.number(), &signer.address()) {
header.set_difficulty(DIFF_INTURN);
} else {
header.set_difficulty(DIFF_NOTURN);
}
}
let zero_padding_len = VANITY_LENGTH - header.extra_data().len();
if zero_padding_len > 0 {
let mut resized_extra_data = header.extra_data().clone();
resized_extra_data.resize(VANITY_LENGTH, 0);
header.set_extra_data(resized_extra_data);
}
} else {
trace!(target: "engine", "populate_from_parent: no signer registered");
}
}
}
fn set_signer(&self, signer: Box<EngineSigner>) {
trace!(target: "engine", "set_signer: {}", signer.address());
*self.signer.write() = Some(signer);
}
fn register_client(&self, client: Weak<EngineClient>) {
*self.client.write() = Some(client.clone());
}
fn step(&self) {
if self.signer.read().is_some() {
if let Some(ref weak) = *self.client.read() {
if let Some(c) = weak.upgrade() {
c.update_sealing();
}
}
}
}
fn stop(&mut self) {
if let Some(mut s) = self.step_service.as_mut() {
Arc::get_mut(&mut s).map(|x| x.stop());
} else {
warn!(target: "engine", "Stopping `CliqueStepService` failed requires mutable access");
}
}
/// Clique timestamp is set to parent + period , or current time which ever is higher.
fn open_block_header_timestamp(&self, parent_timestamp: u64) -> u64 {
let now = time::SystemTime::now().duration_since(time::UNIX_EPOCH).unwrap_or_default();
cmp::max(now.as_secs() as u64, parent_timestamp.saturating_add(self.period))
}
fn is_timestamp_valid(&self, header_timestamp: u64, parent_timestamp: u64) -> bool {
header_timestamp >= parent_timestamp.saturating_add(self.period)
}
fn fork_choice(&self, new: &ExtendedHeader, current: &ExtendedHeader) -> super::ForkChoice {
super::total_difficulty_fork_choice(new, current)
}
// Clique uses the author field for voting, the real author is hidden in the `extra_data` field.
// So when executing tx's (like in `enact()`) we want to use the executive author
fn executive_author(&self, header: &Header) -> Result<Address, Error> {
recover_creator(header)
}
}

View File

@@ -0,0 +1,41 @@
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.
// Parity Ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
//! Clique specific parameters.
use ethjson;
/// `Clique` params.
pub struct CliqueParams {
/// Period as defined in EIP
pub period: u64,
/// Epoch length as defined in EIP
pub epoch: u64,
}
impl From<ethjson::spec::CliqueParams> for CliqueParams {
fn from(p: ethjson::spec::CliqueParams) -> Self {
let period = p.period.map_or_else(|| 30000 as u64, Into::into);
let epoch = p.epoch.map_or_else(|| 15 as u64, Into::into);
assert!(epoch > 0);
CliqueParams {
period,
epoch,
}
}
}

View File

@@ -0,0 +1,77 @@
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.
// Parity Ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use std::sync::Weak;
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Duration;
use std::thread;
use std::sync::Arc;
use engines::Engine;
use machine::Machine;
/// Service that is managing the engine
pub struct StepService {
shutdown: Arc<AtomicBool>,
thread: Option<thread::JoinHandle<()>>,
}
impl StepService {
/// Start the `StepService`
pub fn start<M: Machine + 'static>(engine: Weak<Engine<M>>) -> Arc<Self> {
let shutdown = Arc::new(AtomicBool::new(false));
let s = shutdown.clone();
let thread = thread::Builder::new()
.name("CliqueStepService".into())
.spawn(move || {
// startup delay.
thread::sleep(Duration::from_secs(5));
loop {
// see if we are in shutdown.
if shutdown.load(Ordering::Acquire) {
trace!(target: "miner", "CliqueStepService: received shutdown signal!");
break;
}
trace!(target: "miner", "CliqueStepService: triggering sealing");
// Try sealing
engine.upgrade().map(|x| x.step());
// Yield
thread::sleep(Duration::from_millis(2000));
}
trace!(target: "miner", "CliqueStepService: shutdown.");
}).expect("CliqueStepService thread failed");
Arc::new(StepService {
shutdown: s,
thread: Some(thread),
})
}
/// Stop the `StepService`
pub fn stop(&mut self) {
trace!(target: "miner", "CliqueStepService: shutting down.");
self.shutdown.store(true, Ordering::Release);
if let Some(t) = self.thread.take() {
t.join().expect("CliqueStepService thread panicked!");
}
}
}

View File

@@ -0,0 +1,804 @@
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.
// Parity Ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
//! Consensus tests for `PoA Clique Engine`, see http://eips.ethereum.org/EIPS/eip-225 for more information
use block::*;
use engines::Engine;
use error::{Error, ErrorKind};
use ethereum_types::{Address, H256};
use ethkey::{Secret, KeyPair};
use state_db::StateDB;
use super::*;
use test_helpers::get_temp_state_db;
use std::sync::Arc;
use std::collections::HashMap;
/// Possible signers
pub const SIGNER_TAGS: [char; 6] = ['A', 'B', 'C', 'D', 'E', 'F'];
/// Clique block types
pub enum CliqueBlockType {
/// Epoch transition block must contain list of signers
Checkpoint,
/// Block with no votes
Empty,
/// Vote
Vote(VoteType),
}
/// Clique tester
pub struct CliqueTester {
/// Mocked Clique
pub clique: Clique,
/// Mocked genesis state
pub genesis: Header,
/// StateDB
pub db: StateDB,
/// List of signers
pub signers: HashMap<char, KeyPair>,
}
impl CliqueTester {
/// Create a `Clique` tester with settings
pub fn with(epoch: u64, period: u64, initial_signers: Vec<char>) -> Self {
assert_eq!(initial_signers.iter().all(|s| SIGNER_TAGS.contains(s)), true,
"Not all the initial signers is in SIGNER_TAGS, possible keys are 'A' ..= 'F'");
let clique = Clique::with_test(epoch, period);
let mut genesis = Header::default();
let mut signers = HashMap::new();
let call = |_a, _b| {
unimplemented!("Clique doesn't use Engine::Call");
};
let mut extra_data = vec![0; VANITY_LENGTH];
for &signer in SIGNER_TAGS.iter() {
let secret = Secret::from(H256::from(signer as u64));
let keypair = KeyPair::from_secret(secret).unwrap();
if initial_signers.contains(&signer) {
extra_data.extend(&*keypair.address());
}
signers.insert(signer, keypair);
}
// append dummy signature
extra_data.extend(std::iter::repeat(0).take(SIGNATURE_LENGTH));
genesis.set_extra_data(extra_data);
genesis.set_gas_limit(U256::from(0xa00000));
genesis.set_difficulty(U256::from(1));
genesis.set_seal(util::null_seal());
clique.genesis_epoch_data(&genesis, &call).expect("Create genesis failed");
Self {clique, genesis, db: get_temp_state_db(), signers}
}
/// Get difficulty for a given block
pub fn get_difficulty(&self, block_num: BlockNumber, header: &Header, signer: &Address) -> U256 {
let state = self.clique.state(header).unwrap();
if state.is_inturn(block_num, signer) {
DIFF_INTURN
} else {
DIFF_NOTURN
}
}
/// Get the state of a given block
// Note, this will read the cache and `will` not work with more than 128 blocks
pub fn get_state_at_block(&self, hash: &H256) -> CliqueBlockState {
self.clique.block_state_by_hash.write()
.get_mut(hash)
.expect("CliqueBlockState not found tested failed")
.clone()
}
/// Get signers after a certain state
// This is generally used to fetch the state after a test has been executed and checked against
// the intial list of signers provided in the test
pub fn clique_signers(&self, hash: &H256) -> impl Iterator<Item = Address> {
self.get_state_at_block(hash).signers().clone().into_iter()
}
/// Fetches all addresses at current `block` and converts them back to `tags (char)` and sorts them
/// Addresses are supposed sorted based on address but these tests are using `tags` just for simplicity
/// and the order is not important!
pub fn into_tags<T: Iterator<Item = Address>>(&self, addr: T) -> Vec<char> {
let mut tags: Vec<char> = addr.filter_map(|addr| {
for (t, kp) in self.signers.iter() {
if addr == kp.address() {
return Some(*t)
}
}
None
})
.collect();
tags.sort();
tags
}
/// Create a new `Clique` block and import
pub fn new_block_and_import(
&self,
block_type: CliqueBlockType,
last_header: &Header,
beneficary: Option<Address>,
signer: char,
) -> Result<Header, Error> {
let mut extra_data = vec![0; VANITY_LENGTH];
let mut seal = util::null_seal();
let last_hash = last_header.hash();
match block_type {
CliqueBlockType::Checkpoint => {
let signers = self.clique.state(&last_header).unwrap().signers().clone();
for signer in signers {
extra_data.extend(&*signer);
}
}
CliqueBlockType::Vote(v) => seal = v.as_rlp(),
CliqueBlockType::Empty => (),
};
let db = self.db.boxed_clone();
let mut block = OpenBlock::new(
&self.clique,
Default::default(),
false,
db,
&last_header.clone(),
Arc::new(vec![last_hash]),
beneficary.unwrap_or_default(),
(3141562.into(), 31415620.into()),
extra_data,
false,
None,
).unwrap();
{
let difficulty = self.get_difficulty(block.header.number(), last_header, &self.signers[&signer].address());
let b = block.block_mut();
b.header.set_timestamp(last_header.timestamp() + self.clique.period);
b.header.set_difficulty(difficulty);
b.header.set_seal(seal);
let sign = ethkey::sign(self.signers[&signer].secret(), &b.header.hash()).unwrap();
let mut extra_data = b.header.extra_data().clone();
extra_data.extend_from_slice(&*sign);
b.header.set_extra_data(extra_data);
}
let current_header = &block.header;
self.clique.verify_block_basic(current_header)?;
self.clique.verify_block_family(current_header, &last_header)?;
Ok(current_header.clone())
}
}
#[test]
fn one_signer_with_no_votes() {
let tester = CliqueTester::with(10, 1, vec!['A']);
let empty_block = tester.new_block_and_import(CliqueBlockType::Empty, &tester.genesis, None, 'A').unwrap();
let tags = tester.into_tags(tester.clique_signers(&empty_block.hash()));
assert_eq!(&tags, &['A']);
}
#[test]
fn one_signer_two_votes() {
let tester = CliqueTester::with(10, 1, vec!['A']);
// Add a vote for `B` signed by `A`
let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &tester.genesis,
Some(tester.signers[&'B'].address()), 'A').unwrap();
let tags = tester.into_tags(tester.clique_signers(&vote.hash()));
assert_eq!(&tags, &['A', 'B']);
// Add a empty block signed by `B`
let empty = tester.new_block_and_import(CliqueBlockType::Empty, &vote, None, 'B').unwrap();
// Add vote for `C` signed by A but should not be accepted
let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &empty,
Some(tester.signers[&'C'].address()), 'A').unwrap();
let tags = tester.into_tags(tester.clique_signers(&vote.hash()));
assert_eq!(&tags, &['A', 'B']);
}
#[test]
fn two_signers_six_votes_deny_last() {
let tester = CliqueTester::with(10, 1, vec!['A', 'B']);
let mut prev_header = tester.genesis.clone();
// Add two votes for `C` signed by `A` and `B`
for &signer in SIGNER_TAGS.iter().take(2) {
let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &prev_header,
Some(tester.signers[&'C'].address()), signer).unwrap();
prev_header = vote.clone();
}
// Add two votes for `D` signed by `A` and `B`
for &signer in SIGNER_TAGS.iter().take(2) {
let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &prev_header,
Some(tester.signers[&'D'].address()), signer).unwrap();
prev_header = vote.clone();
}
// Add a empty block signed by `C`
let empty = tester.new_block_and_import(CliqueBlockType::Empty, &prev_header, None, 'C').unwrap();
prev_header = empty.clone();
// Add two votes for `E` signed by `A` and `B`
for &signer in SIGNER_TAGS.iter().take(2) {
let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &prev_header,
Some(tester.signers[&'E'].address()), signer).unwrap();
prev_header = vote.clone();
}
let tags = tester.into_tags(tester.clique_signers(&prev_header.hash()));
assert_eq!(&tags, &['A', 'B', 'C', 'D']);
}
#[test]
fn one_signer_dropping_itself() {
let tester = CliqueTester::with(10, 1, vec!['A']);
let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &tester.genesis,
Some(tester.signers[&'A'].address()), 'A').unwrap();
let signers = tester.clique_signers(&vote.hash());
assert!(signers.count() == 0);
}
#[test]
fn two_signers_one_remove_vote_no_consensus() {
let tester = CliqueTester::with(10, 1, vec!['A', 'B']);
let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &tester.genesis,
Some(tester.signers[&'B'].address()), 'A').unwrap();
let tags = tester.into_tags(tester.clique_signers(&vote.hash()));
assert_eq!(&tags, &['A', 'B']);
}
#[test]
fn two_signers_consensus_remove_b() {
let tester = CliqueTester::with(10, 1, vec!['A', 'B']);
let first_vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &tester.genesis,
Some(tester.signers[&'B'].address()), 'A').unwrap();
let second_vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &first_vote,
Some(tester.signers[&'B'].address()), 'B').unwrap();
let tags = tester.into_tags(tester.clique_signers(&second_vote.hash()));
assert_eq!(&tags, &['A']);
}
#[test]
fn three_signers_consensus_remove_c() {
let tester = CliqueTester::with(10, 1, vec!['A', 'B', 'C']);
let first_vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &tester.genesis,
Some(tester.signers[&'C'].address()), 'A').unwrap();
let second_vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &first_vote,
Some(tester.signers[&'C'].address()), 'B').unwrap();
let tags = tester.into_tags(tester.clique_signers(&second_vote.hash()));
assert_eq!(&tags, &['A', 'B']);
}
#[test]
fn four_signers_half_no_consensus() {
let tester = CliqueTester::with(10, 1, vec!['A', 'B', 'C', 'D']);
let first_vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &tester.genesis,
Some(tester.signers[&'C'].address()), 'A').unwrap();
let second_vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &first_vote,
Some(tester.signers[&'C'].address()), 'B').unwrap();
let tags = tester.into_tags(tester.clique_signers(&second_vote.hash()));
assert_eq!(&tags, &['A', 'B', 'C', 'D']);
}
#[test]
fn four_signers_three_consensus_rm() {
let tester = CliqueTester::with(10, 1, vec!['A', 'B', 'C', 'D']);
let mut prev_header = tester.genesis.clone();
// Three votes to remove `D` signed by ['A', 'B', 'C']
for signer in SIGNER_TAGS.iter().take(3) {
let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &prev_header,
Some(tester.signers[&'D'].address()), *signer).unwrap();
prev_header = vote.clone();
}
let tags = tester.into_tags(tester.clique_signers(&prev_header.hash()));
assert_eq!(&tags, &['A', 'B', 'C']);
}
#[test]
fn vote_add_only_counted_once_per_signer() {
let tester = CliqueTester::with(10, 1, vec!['A', 'B']);
// Add a vote for `C` signed by `A`
let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &tester.genesis,
Some(tester.signers[&'C'].address()), 'A').unwrap();
// Empty block signed by B`
let empty = tester.new_block_and_import(CliqueBlockType::Empty, &vote, None, 'B').unwrap();
// Add a vote for `C` signed by `A`
let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &empty,
Some(tester.signers[&'C'].address()), 'A').unwrap();
// Empty block signed by `B`
let empty = tester.new_block_and_import(CliqueBlockType::Empty, &vote, None, 'B').unwrap();
// Add a vote for `C` signed by `A`
let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &empty,
Some(tester.signers[&'C'].address()), 'A').unwrap();
let tags = tester.into_tags(tester.clique_signers(&vote.hash()));
assert_eq!(&tags, &['A', 'B']);
}
#[test]
fn vote_add_concurrently_is_permitted() {
let tester = CliqueTester::with(10, 1, vec!['A', 'B']);
// Add a vote for `C` signed by `A`
let b = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &tester.genesis,
Some(tester.signers[&'C'].address()), 'A').unwrap();
// Empty block signed by `B`
let b = tester.new_block_and_import(CliqueBlockType::Empty, &b, None, 'B').unwrap();
// Add a vote for `D` signed by `A`
let b = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &b,
Some(tester.signers[&'D'].address()), 'A').unwrap();
// Empty block signed by `B`
let b = tester.new_block_and_import(CliqueBlockType::Empty, &b, None, 'B').unwrap();
// Empty block signed by `A`
let b = tester.new_block_and_import(CliqueBlockType::Empty, &b, None, 'A').unwrap();
// Add a vote for `D` signed by `B`
let b = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &b,
Some(tester.signers[&'D'].address()), 'B').unwrap();
// Empty block signed by `A`
let b = tester.new_block_and_import(CliqueBlockType::Empty, &b, None, 'A').unwrap();
// Add a vote for `C` signed by `B`
let b = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &b,
Some(tester.signers[&'C'].address()), 'B').unwrap();
let tags = tester.into_tags(tester.clique_signers(&b.hash()));
assert_eq!(&tags, &['A', 'B', 'C', 'D']);
}
#[test]
fn vote_rm_only_counted_once_per_signer() {
let tester = CliqueTester::with(10, 1, vec!['A', 'B']);
let mut prev_header = tester.genesis.clone();
for _ in 0..2 {
// Vote to remove `B` signed by `A`
let b = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &prev_header,
Some(tester.signers[&'B'].address()), 'A').unwrap();
// Empty block signed by `B`
let b = tester.new_block_and_import(CliqueBlockType::Empty, &b, None, 'B').unwrap();
prev_header = b.clone();
}
// Add a vote for `B` signed by `A`
let b = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &prev_header,
Some(tester.signers[&'B'].address()), 'A').unwrap();
let tags = tester.into_tags(tester.clique_signers(&b.hash()));
assert_eq!(&tags, &['A', 'B']);
}
#[test]
fn vote_rm_concurrently_is_permitted() {
let tester = CliqueTester::with(100, 1, vec!['A', 'B', 'C', 'D']);
// Add a vote for `C` signed by `A`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &tester.genesis,
Some(tester.signers[&'C'].address()), 'A').unwrap();
// Empty block signed by `B`
let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'B').unwrap();
// Empty block signed by `C`
let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'C').unwrap();
// Add a vote for `D` signed by `A`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block,
Some(tester.signers[&'D'].address()), 'A').unwrap();
// Empty block signed by `B`
let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'B').unwrap();
// Empty block signed by `C`
let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'C').unwrap();
// Empty block signed by `A`
let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'A').unwrap();
// Add a vote for `D` signed by `B`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block,
Some(tester.signers[&'D'].address()), 'B').unwrap();
// Add a vote for `D` signed by `C`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block,
Some(tester.signers[&'D'].address()), 'C').unwrap();
// Empty block signed by `A`
let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'A').unwrap();
// Add a vote for `C` signed by `B`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block,
Some(tester.signers[&'C'].address()), 'B').unwrap();
let tags = tester.into_tags(tester.clique_signers(&block.hash()));
assert_eq!(&tags, &['A', 'B']);
}
#[test]
fn vote_to_rm_are_immediate_and_ensure_votes_are_rm() {
let tester = CliqueTester::with(100, 1, vec!['A', 'B', 'C']);
// Vote to remove `B` signed by `C`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &tester.genesis,
Some(tester.signers[&'B'].address()), 'C').unwrap();
// Vote to remove `C` signed by `A`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block,
Some(tester.signers[&'C'].address()), 'A').unwrap();
// Vote to remove `C` signed by `B`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block,
Some(tester.signers[&'C'].address()), 'B').unwrap();
// Vote to remove `B` signed by `A`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block,
Some(tester.signers[&'B'].address()), 'A').unwrap();
let tags = tester.into_tags(tester.clique_signers(&block.hash()));
assert_eq!(&tags, &['A', 'B']);
}
#[test]
fn vote_to_rm_are_immediate_and_votes_should_be_dropped_from_kicked_signer() {
let tester = CliqueTester::with(100, 1, vec!['A', 'B', 'C']);
// Vote to add `D` signed by `C`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &tester.genesis,
Some(tester.signers[&'D'].address()), 'C').unwrap();
// Vote to remove `C` signed by `A`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block,
Some(tester.signers[&'C'].address()), 'A').unwrap();
// Vote to remove `C` signed by `B`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block,
Some(tester.signers[&'C'].address()), 'B').unwrap();
// Vote to add `D` signed by `A`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &block,
Some(tester.signers[&'D'].address()), 'A').unwrap();
let tags = tester.into_tags(tester.clique_signers(&block.hash()));
assert_eq!(&tags, &['A', 'B']);
}
#[test]
fn cascading_not_allowed() {
let tester = CliqueTester::with(100, 1, vec!['A', 'B', 'C', 'D']);
// Vote against `C` signed by `A`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &tester.genesis,
Some(tester.signers[&'C'].address()), 'A').unwrap();
// Empty block signed by `B`
let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'B').unwrap();
// Empty block signed by `C`
let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'C').unwrap();
// Vote against `D` signed by `A`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block,
Some(tester.signers[&'D'].address()), 'A').unwrap();
// Vote against `C` signed by `B`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block,
Some(tester.signers[&'C'].address()), 'B').unwrap();
// Empty block signed by `C`
let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'C').unwrap();
// Empty block signed by `A`
let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'A').unwrap();
// Vote against `D` signed by `B`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block,
Some(tester.signers[&'D'].address()), 'B').unwrap();
// Vote against `D` signed by `C`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block,
Some(tester.signers[&'D'].address()), 'C').unwrap();
let tags = tester.into_tags(tester.clique_signers(&block.hash()));
assert_eq!(&tags, &['A', 'B', 'C']);
}
#[test]
fn consensus_out_of_bounds_consensus_execute_on_touch() {
let tester = CliqueTester::with(100, 1, vec!['A', 'B', 'C', 'D']);
// Vote against `C` signed by `A`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &tester.genesis,
Some(tester.signers[&'C'].address()), 'A').unwrap();
// Empty block signed by `B`
let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'B').unwrap();
// Empty block signed by `C`
let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'C').unwrap();
// Vote against `D` signed by `A`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block,
Some(tester.signers[&'D'].address()), 'A').unwrap();
// Vote against `C` signed by `B`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block,
Some(tester.signers[&'C'].address()), 'B').unwrap();
// Empty block signed by `C`
let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'C').unwrap();
// Empty block signed by `A`
let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'A').unwrap();
// Vote against `D` signed by `B`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block,
Some(tester.signers[&'D'].address()), 'B').unwrap();
// Vote against `D` signed by `C`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block,
Some(tester.signers[&'D'].address()), 'C').unwrap();
let tags = tester.into_tags(tester.clique_signers(&block.hash()));
assert_eq!(&tags, &['A', 'B', 'C'], "D should have been removed after 3/4 remove votes");
// Empty block signed by `A`
let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'A').unwrap();
// Vote for `C` signed by `C`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &block,
Some(tester.signers[&'C'].address()), 'C').unwrap();
let tags = tester.into_tags(tester.clique_signers(&block.hash()));
assert_eq!(&tags, &['A', 'B']);
}
#[test]
fn consensus_out_of_bounds_first_touch() {
let tester = CliqueTester::with(100, 1, vec!['A', 'B', 'C', 'D']);
// Vote against `C` signed by `A`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &tester.genesis,
Some(tester.signers[&'C'].address()), 'A').unwrap();
// Empty block signed by `B`
let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'B').unwrap();
// Empty block signed by `C`
let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'C').unwrap();
// Vote against `D` signed by `A`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block,
Some(tester.signers[&'D'].address()), 'A').unwrap();
// Vote against `C` signed by `B`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block,
Some(tester.signers[&'C'].address()), 'B').unwrap();
// Empty block signed by `C`
let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'C').unwrap();
// Empty block signed by `A`
let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'A').unwrap();
// Vote against `D` signed by `B`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block,
Some(tester.signers[&'D'].address()), 'B').unwrap();
// Vote against `D` signed by `C`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &block,
Some(tester.signers[&'D'].address()), 'C').unwrap();
let tags = tester.into_tags(tester.clique_signers(&block.hash()));
assert_eq!(&tags, &['A', 'B', 'C']);
// Empty block signed by `A`
let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'A').unwrap();
// Vote for `C` signed by `B`
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &block,
Some(tester.signers[&'C'].address()), 'B').unwrap();
let tags = tester.into_tags(tester.clique_signers(&block.hash()));
assert_eq!(&tags, &['A', 'B', 'C']);
}
#[test]
fn pending_votes_doesnt_survive_authorization_changes() {
let tester = CliqueTester::with(100, 1, vec!['A', 'B', 'C', 'D', 'E']);
let mut prev_header = tester.genesis.clone();
// Vote for `F` from [`A`, `B`, `C`]
for sign in SIGNER_TAGS.iter().take(3) {
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &prev_header,
Some(tester.signers[&'F'].address()), *sign).unwrap();
prev_header = block.clone();
}
let tags = tester.into_tags(tester.clique_signers(&prev_header.hash()));
assert_eq!(&tags, &['A', 'B', 'C', 'D', 'E', 'F'], "F should have been added");
// Vote against `F` from [`D`, `E`, `B`, `C`]
for sign in SIGNER_TAGS.iter().skip(3).chain(SIGNER_TAGS.iter().skip(1).take(2)) {
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &prev_header,
Some(tester.signers[&'F'].address()), *sign).unwrap();
prev_header = block.clone();
}
let tags = tester.into_tags(tester.clique_signers(&prev_header.hash()));
assert_eq!(&tags, &['A', 'B', 'C', 'D', 'E'], "F should have been removed");
// Vote for `F` from [`D`, `E`]
for sign in SIGNER_TAGS.iter().skip(3).take(2) {
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &prev_header,
Some(tester.signers[&'F'].address()), *sign).unwrap();
prev_header = block.clone();
}
// Vote against `A` from [`B`, `C`, `D`]
for sign in SIGNER_TAGS.iter().skip(1).take(3) {
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Remove), &prev_header,
Some(tester.signers[&'A'].address()), *sign).unwrap();
prev_header = block.clone();
}
let tags = tester.into_tags(tester.clique_signers(&prev_header.hash()));
assert_eq!(&tags, &['B', 'C', 'D', 'E'], "A should have been removed");
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &prev_header,
Some(tester.signers[&'F'].address()), 'B').unwrap();
let tags = tester.into_tags(tester.clique_signers(&block.hash()));
assert_eq!(&tags, &['B', 'C', 'D', 'E', 'F'], "F should have been added again");
}
#[test]
fn epoch_transition_reset_all_votes() {
let tester = CliqueTester::with(3, 1, vec!['A', 'B']);
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &tester.genesis,
Some(tester.signers[&'C'].address()), 'A').unwrap();
let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'B').unwrap();
let block = tester.new_block_and_import(CliqueBlockType::Checkpoint, &block, None, 'A').unwrap();
let block = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &block,
Some(tester.signers[&'C'].address()), 'B').unwrap();
let tags = tester.into_tags(tester.clique_signers(&block.hash()));
assert_eq!(&tags, &['A', 'B'], "Votes should have been reset after checkpoint");
}
#[test]
fn unauthorized_signer_should_not_be_able_to_sign_block() {
let tester = CliqueTester::with(3, 1, vec!['A']);
let err = tester.new_block_and_import(CliqueBlockType::Empty, &tester.genesis, None, 'B').unwrap_err();
match err.kind() {
ErrorKind::Engine(EngineError::NotAuthorized(_)) => (),
_ => assert!(true == false, "Wrong error kind"),
}
}
#[test]
fn signer_should_not_be_able_to_sign_two_consequtive_blocks() {
let tester = CliqueTester::with(3, 1, vec!['A', 'B']);
let b = tester.new_block_and_import(CliqueBlockType::Empty, &tester.genesis, None, 'A').unwrap();
let err = tester.new_block_and_import(CliqueBlockType::Empty, &b, None, 'A').unwrap_err();
match err.kind() {
ErrorKind::Engine(EngineError::CliqueTooRecentlySigned(_)) => (),
_ => assert!(true == false, "Wrong error kind"),
}
}
#[test]
fn recent_signers_should_not_reset_on_checkpoint() {
let tester = CliqueTester::with(3, 1, vec!['A', 'B', 'C']);
let block = tester.new_block_and_import(CliqueBlockType::Empty, &tester.genesis, None, 'A').unwrap();
let block = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'B').unwrap();
let block = tester.new_block_and_import(CliqueBlockType::Checkpoint, &block, None, 'A').unwrap();
let err = tester.new_block_and_import(CliqueBlockType::Empty, &block, None, 'A').unwrap_err();
match err.kind() {
ErrorKind::Engine(EngineError::CliqueTooRecentlySigned(_)) => (),
_ => assert!(true == false, "Wrong error kind"),
}
}
// Not part of http://eips.ethereum.org/EIPS/eip-225
#[test]
fn bonus_consensus_should_keep_track_of_votes_before_latest_per_signer() {
let tester = CliqueTester::with(100, 1, vec!['A', 'B', 'C', 'D']);
// Add a vote for `E` signed by `A`
let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &tester.genesis,
Some(tester.signers[&'E'].address()), 'A').unwrap();
// Empty block signed by `B`
let vote = tester.new_block_and_import(CliqueBlockType::Empty, &vote, None, 'B').unwrap();
// Empty block signed by `C`
let vote = tester.new_block_and_import(CliqueBlockType::Empty, &vote, None, 'C').unwrap();
// Empty block signed by `D`
let vote = tester.new_block_and_import(CliqueBlockType::Empty, &vote, None, 'D').unwrap();
// Add a vote for `F` signed by `A`
let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &vote,
Some(tester.signers[&'F'].address()), 'A').unwrap();
// Empty block signed by `C`
let vote = tester.new_block_and_import(CliqueBlockType::Empty, &vote, None, 'C').unwrap();
// Empty block signed by `D`
let vote = tester.new_block_and_import(CliqueBlockType::Empty, &vote, None, 'D').unwrap();
// Add a vote for `E` signed by `B`
let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &vote,
Some(tester.signers[&'E'].address()), 'B').unwrap();
// Empty block signed by `A`
let vote = tester.new_block_and_import(CliqueBlockType::Empty, &vote, None, 'A').unwrap();
// Empty block signed by `C`
let vote = tester.new_block_and_import(CliqueBlockType::Empty, &vote, None, 'C').unwrap();
// Empty block signed by `D`
let vote = tester.new_block_and_import(CliqueBlockType::Empty, &vote, None, 'D').unwrap();
// Add a vote for `F` signed by `B`
let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &vote,
Some(tester.signers[&'F'].address()), 'B').unwrap();
// Empty block signed by A`
let vote = tester.new_block_and_import(CliqueBlockType::Empty, &vote, None, 'A').unwrap();
// Add a vote for `E` signed by `C`
let vote = tester.new_block_and_import(CliqueBlockType::Vote(VoteType::Add), &vote,
Some(tester.signers[&'E'].address()), 'C').unwrap();
let tags = tester.into_tags(tester.clique_signers(&vote.hash()));
assert_eq!(&tags, &['A', 'B', 'C', 'D', 'E']);
}

View File

@@ -0,0 +1,115 @@
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.
// Parity Ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use std::collections::BTreeSet;
use engines::EngineError;
use engines::clique::{ADDRESS_LENGTH, SIGNATURE_LENGTH, VANITY_LENGTH, NULL_NONCE, NULL_MIXHASH};
use error::Error;
use ethereum_types::{Address, H256};
use ethkey::{public_to_address, recover as ec_recover, Signature};
use lru_cache::LruCache;
use parking_lot::RwLock;
use rlp::encode;
use types::header::Header;
/// How many recovered signature to cache in the memory.
pub const CREATOR_CACHE_NUM: usize = 4096;
lazy_static! {
/// key: header hash
/// value: creator address
static ref CREATOR_BY_HASH: RwLock<LruCache<H256, Address>> = RwLock::new(LruCache::new(CREATOR_CACHE_NUM));
}
/// Recover block creator from signature
pub fn recover_creator(header: &Header) -> Result<Address, Error> {
// Initialization
let mut cache = CREATOR_BY_HASH.write();
if let Some(creator) = cache.get_mut(&header.hash()) {
return Ok(*creator);
}
let data = header.extra_data();
if data.len() < VANITY_LENGTH {
Err(EngineError::CliqueMissingVanity)?
}
if data.len() < VANITY_LENGTH + SIGNATURE_LENGTH {
Err(EngineError::CliqueMissingSignature)?
}
// Split `signed_extra data` and `signature`
let (signed_data_slice, signature_slice) = data.split_at(data.len() - SIGNATURE_LENGTH);
// convert `&[u8]` to `[u8; 65]`
let signature = {
let mut s = [0; SIGNATURE_LENGTH];
s.copy_from_slice(signature_slice);
s
};
// modify header and hash it
let unsigned_header = &mut header.clone();
unsigned_header.set_extra_data(signed_data_slice.to_vec());
let msg = unsigned_header.hash();
let pubkey = ec_recover(&Signature::from(signature), &msg)?;
let creator = public_to_address(&pubkey);
cache.insert(header.hash(), creator.clone());
Ok(creator)
}
/// Extract signer list from extra_data.
///
/// Layout of extra_data:
/// ----
/// VANITY: 32 bytes
/// Signers: N * 32 bytes as hex encoded (20 characters)
/// Signature: 65 bytes
/// --
pub fn extract_signers(header: &Header) -> Result<BTreeSet<Address>, Error> {
let data = header.extra_data();
if data.len() <= VANITY_LENGTH + SIGNATURE_LENGTH {
Err(EngineError::CliqueCheckpointNoSigner)?
}
// extract only the portion of extra_data which includes the signer list
let signers_raw = &data[(VANITY_LENGTH)..data.len() - (SIGNATURE_LENGTH)];
if signers_raw.len() % ADDRESS_LENGTH != 0 {
Err(EngineError::CliqueCheckpointInvalidSigners(signers_raw.len()))?
}
let num_signers = signers_raw.len() / 20;
let signers: BTreeSet<Address> = (0..num_signers)
.map(|i| {
let start = i * ADDRESS_LENGTH;
let end = start + ADDRESS_LENGTH;
signers_raw[start..end].into()
})
.collect();
Ok(signers)
}
/// Retrieve `null_seal`
pub fn null_seal() -> Vec<Vec<u8>> {
vec![encode(&NULL_MIXHASH.to_vec()), encode(&NULL_NONCE.to_vec())]
}

View File

@@ -15,7 +15,9 @@
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use engines::{Engine, Seal};
use parity_machine::{Machine, Transactions, TotalScoredHeader};
use machine::Machine;
use types::header::{Header, ExtendedHeader};
use block::ExecutedBlock;
/// `InstantSeal` params.
#[derive(Default, Debug, PartialEq)]
@@ -48,11 +50,7 @@ impl<M> InstantSeal<M> {
}
}
impl<M: Machine> Engine<M> for InstantSeal<M>
where M::LiveBlock: Transactions,
M::ExtendedHeader: TotalScoredHeader,
<M::ExtendedHeader as TotalScoredHeader>::Value: Ord
{
impl<M: Machine> Engine<M> for InstantSeal<M> {
fn name(&self) -> &str {
"InstantSeal"
}
@@ -61,11 +59,15 @@ impl<M: Machine> Engine<M> for InstantSeal<M>
fn seals_internally(&self) -> Option<bool> { Some(true) }
fn generate_seal(&self, block: &M::LiveBlock, _parent: &M::Header) -> Seal {
if block.transactions().is_empty() { Seal::None } else { Seal::Regular(Vec::new()) }
fn generate_seal(&self, block: &ExecutedBlock, _parent: &Header) -> Seal {
if block.transactions.is_empty() {
Seal::None
} else {
Seal::Regular(Vec::new())
}
}
fn verify_local_seal(&self, _header: &M::Header) -> Result<(), M::Error> {
fn verify_local_seal(&self, _header: &Header) -> Result<(), M::Error> {
Ok(())
}
@@ -84,7 +86,7 @@ impl<M: Machine> Engine<M> for InstantSeal<M>
header_timestamp >= parent_timestamp
}
fn fork_choice(&self, new: &M::ExtendedHeader, current: &M::ExtendedHeader) -> super::ForkChoice {
fn fork_choice(&self, new: &ExtendedHeader, current: &ExtendedHeader) -> super::ForkChoice {
super::total_difficulty_fork_choice(new, current)
}
}
@@ -106,9 +108,9 @@ mod tests {
let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap();
let genesis_header = spec.genesis_header();
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::default(), (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::default(), (3141562.into(), 31415620.into()), vec![], false, None).unwrap();
let b = b.close_and_lock().unwrap();
if let Seal::Regular(seal) = engine.generate_seal(b.block(), &genesis_header) {
if let Seal::Regular(seal) = engine.generate_seal(&b, &genesis_header) {
assert!(b.try_seal(engine, seal).is_ok());
}
}

View File

@@ -18,6 +18,7 @@
mod authority_round;
mod basic_authority;
mod clique;
mod instant_seal;
mod null_engine;
mod validator_set;
@@ -27,14 +28,14 @@ pub mod signer;
pub use self::authority_round::AuthorityRound;
pub use self::basic_authority::BasicAuthority;
pub use self::epoch::{EpochVerifier, Transition as EpochTransition};
pub use self::instant_seal::{InstantSeal, InstantSealParams};
pub use self::null_engine::NullEngine;
pub use self::signer::EngineSigner;
pub use self::clique::Clique;
// TODO [ToDr] Remove re-export (#10130)
pub use types::engines::ForkChoice;
pub use types::engines::epoch;
pub use types::engines::epoch::{self, Transition as EpochTransition};
use std::sync::{Weak, Arc};
use std::collections::{BTreeMap, HashMap};
@@ -44,21 +45,24 @@ use builtin::Builtin;
use vm::{EnvInfo, Schedule, CreateContractAddress, CallType, ActionValue};
use error::Error;
use types::BlockNumber;
use types::header::Header;
use types::header::{Header, ExtendedHeader};
use snapshot::SnapshotComponents;
use spec::CommonParams;
use types::transaction::{self, UnverifiedTransaction, SignedTransaction};
use ethkey::{Signature};
use parity_machine::{Machine, LocalizedMachine as Localized, TotalScoredHeader};
use ethereum_types::{H256, U256, Address};
use machine::{self, Machine, AuxiliaryRequest, AuxiliaryData};
use ethereum_types::{H64, H256, U256, Address};
use unexpected::{Mismatch, OutOfBounds};
use bytes::Bytes;
use types::ancestry_action::AncestryAction;
use block::ExecutedBlock;
/// Default EIP-210 contract code.
/// As defined in https://github.com/ethereum/EIPs/pull/210
pub const DEFAULT_BLOCKHASH_CONTRACT: &'static str = "73fffffffffffffffffffffffffffffffffffffffe33141561006a5760014303600035610100820755610100810715156100455760003561010061010083050761010001555b6201000081071515610064576000356101006201000083050761020001555b5061013e565b4360003512151561008457600060405260206040f361013d565b61010060003543031315156100a857610100600035075460605260206060f361013c565b6101006000350715156100c55762010000600035430313156100c8565b60005b156100ea576101006101006000350507610100015460805260206080f361013b565b620100006000350715156101095763010000006000354303131561010c565b60005b1561012f57610100620100006000350507610200015460a052602060a0f361013a565b600060c052602060c0f35b5b5b5b5b";
/// The number of generations back that uncles can be.
pub const MAX_UNCLE_AGE: usize = 6;
/// Voting errors.
#[derive(Debug)]
@@ -83,12 +87,45 @@ pub enum EngineError {
RequiresClient,
/// Invalid engine specification or implementation.
InvalidEngine,
/// Requires signer ref, but none registered.
RequiresSigner,
/// Checkpoint is missing
CliqueMissingCheckpoint(H256),
/// Missing vanity data
CliqueMissingVanity,
/// Missing signature
CliqueMissingSignature,
/// Missing signers
CliqueCheckpointNoSigner,
/// List of signers is invalid
CliqueCheckpointInvalidSigners(usize),
/// Wrong author on a checkpoint
CliqueWrongAuthorCheckpoint(Mismatch<Address>),
/// Wrong checkpoint authors recovered
CliqueFaultyRecoveredSigners(Vec<String>),
/// Invalid nonce (should contain vote)
CliqueInvalidNonce(H64),
/// The signer signed a block to recently
CliqueTooRecentlySigned(Address),
/// Custom
Custom(String),
}
impl fmt::Display for EngineError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::EngineError::*;
let msg = match *self {
CliqueMissingCheckpoint(ref hash) => format!("Missing checkpoint block: {}", hash),
CliqueMissingVanity => format!("Extra data is missing vanity data"),
CliqueMissingSignature => format!("Extra data is missing signature"),
CliqueCheckpointInvalidSigners(len) => format!("Checkpoint block list was of length: {} of checkpoint but
it needs to be bigger than zero and a divisible by 20", len),
CliqueCheckpointNoSigner => format!("Checkpoint block list of signers was empty"),
CliqueInvalidNonce(ref mis) => format!("Unexpected nonce {} expected {} or {}", mis, 0_u64, u64::max_value()),
CliqueWrongAuthorCheckpoint(ref oob) => format!("Unexpected checkpoint author: {}", oob),
CliqueFaultyRecoveredSigners(ref mis) => format!("Faulty recovered signers {:?}", mis),
CliqueTooRecentlySigned(ref address) => format!("The signer: {} has signed a block too recently", address),
Custom(ref s) => s.clone(),
DoubleVote(ref address) => format!("Author {} issued too many blocks.", address),
NotProposer(ref mis) => format!("Author is not a current proposer: {}", mis),
NotAuthorized(ref address) => format!("Signer {} is not authorized.", address),
@@ -98,6 +135,7 @@ impl fmt::Display for EngineError {
FailedSystemCall(ref msg) => format!("Failed to make system call: {}", msg),
MalformedMessage(ref msg) => format!("Received malformed consensus message: {}", msg),
RequiresClient => format!("Call requires client but none registered"),
RequiresSigner => format!("Call requires signer but none registered"),
InvalidEngine => format!("Invalid engine specification or implementation"),
};
@@ -118,7 +156,7 @@ pub enum Seal {
Proposal(Vec<Bytes>),
/// Regular block seal; should be part of the blockchain.
Regular(Vec<Bytes>),
/// Engine does generate seal for this block right now.
/// Engine does not generate seal for this block right now.
None,
}
@@ -176,8 +214,7 @@ pub type PendingTransitionStore<'a> = Fn(H256) -> Option<epoch::PendingTransitio
/// Proof dependent on state.
pub trait StateDependentProof<M: Machine>: Send + Sync {
/// Generate a proof, given the state.
// TODO: make this into an &M::StateContext
fn generate_proof<'a>(&self, state: &<M as Localized<'a>>::StateContext) -> Result<Vec<u8>, String>;
fn generate_proof<'a>(&self, state: &machine::Call) -> Result<Vec<u8>, String>;
/// Check a proof generated elsewhere (potentially by a peer).
// `engine` needed to check state proofs, while really this should
// just be state machine params.
@@ -217,7 +254,7 @@ impl<'a, M: Machine> ConstructedVerifier<'a, M> {
/// Results of a query of whether an epoch change occurred at the given block.
pub enum EpochChange<M: Machine> {
/// Cannot determine until more data is passed.
Unsure(M::AuxiliaryRequest),
Unsure(AuxiliaryRequest),
/// No epoch change.
No,
/// The epoch will change, with proof.
@@ -235,17 +272,14 @@ pub trait Engine<M: Machine>: Sync + Send {
fn machine(&self) -> &M;
/// The number of additional header fields required for this engine.
fn seal_fields(&self, _header: &M::Header) -> usize { 0 }
fn seal_fields(&self, _header: &Header) -> usize { 0 }
/// Additional engine-specific information for the user/developer concerning `header`.
fn extra_info(&self, _header: &M::Header) -> BTreeMap<String, String> { BTreeMap::new() }
fn extra_info(&self, _header: &Header) -> BTreeMap<String, String> { BTreeMap::new() }
/// Maximum number of uncles a block is allowed to declare.
fn maximum_uncle_count(&self, _block: BlockNumber) -> usize { 0 }
/// The number of generations back that uncles can be.
fn maximum_uncle_age(&self) -> usize { 6 }
/// Optional maximum gas limit.
fn maximum_gas_limit(&self) -> Option<U256> { None }
@@ -253,18 +287,21 @@ pub trait Engine<M: Machine>: Sync + Send {
/// `epoch_begin` set to true if this block kicks off an epoch.
fn on_new_block(
&self,
_block: &mut M::LiveBlock,
_block: &mut ExecutedBlock,
_epoch_begin: bool,
_ancestry: &mut Iterator<Item=M::ExtendedHeader>,
_ancestry: &mut Iterator<Item = ExtendedHeader>,
) -> Result<(), M::Error> {
Ok(())
}
/// Block transformation functions, after the transactions.
fn on_close_block(&self, _block: &mut M::LiveBlock) -> Result<(), M::Error> {
fn on_close_block(&self, _block: &mut ExecutedBlock) -> Result<(), M::Error> {
Ok(())
}
/// Allow mutating the header during seal generation. Currently only used by Clique.
fn on_seal_block(&self, _block: &mut ExecutedBlock) -> Result<(), Error> { Ok(()) }
/// None means that it requires external input (e.g. PoW) to seal a block.
/// Some(true) means the engine is currently prime for seal generation (i.e. node is the current validator).
/// Some(false) means that the node might seal internally but is not qualified now.
@@ -279,7 +316,7 @@ pub trait Engine<M: Machine>: Sync + Send {
///
/// It is fine to require access to state or a full client for this function, since
/// light clients do not generate seals.
fn generate_seal(&self, _block: &M::LiveBlock, _parent: &M::Header) -> Seal { Seal::None }
fn generate_seal(&self, _block: &ExecutedBlock, _parent: &Header) -> Seal { Seal::None }
/// Verify a locally-generated seal of a header.
///
@@ -291,25 +328,25 @@ pub trait Engine<M: Machine>: Sync + Send {
///
/// It is fine to require access to state or a full client for this function, since
/// light clients do not generate seals.
fn verify_local_seal(&self, header: &M::Header) -> Result<(), M::Error>;
fn verify_local_seal(&self, header: &Header) -> Result<(), M::Error>;
/// Phase 1 quick block verification. Only does checks that are cheap. Returns either a null `Ok` or a general error detailing the problem with import.
/// The verification module can optionally avoid checking the seal (`check_seal`), if seal verification is disabled this method won't be called.
fn verify_block_basic(&self, _header: &M::Header) -> Result<(), M::Error> { Ok(()) }
fn verify_block_basic(&self, _header: &Header) -> Result<(), M::Error> { Ok(()) }
/// Phase 2 verification. Perform costly checks such as transaction signatures. Returns either a null `Ok` or a general error detailing the problem with import.
/// The verification module can optionally avoid checking the seal (`check_seal`), if seal verification is disabled this method won't be called.
fn verify_block_unordered(&self, _header: &M::Header) -> Result<(), M::Error> { Ok(()) }
fn verify_block_unordered(&self, _header: &Header) -> Result<(), M::Error> { Ok(()) }
/// Phase 3 verification. Check block information against parent. Returns either a null `Ok` or a general error detailing the problem with import.
fn verify_block_family(&self, _header: &M::Header, _parent: &M::Header) -> Result<(), M::Error> { Ok(()) }
fn verify_block_family(&self, _header: &Header, _parent: &Header) -> Result<(), M::Error> { Ok(()) }
/// Phase 4 verification. Verify block header against potentially external data.
/// Should only be called when `register_client` has been called previously.
fn verify_block_external(&self, _header: &M::Header) -> Result<(), M::Error> { Ok(()) }
fn verify_block_external(&self, _header: &Header) -> Result<(), M::Error> { Ok(()) }
/// Genesis epoch data.
fn genesis_epoch_data<'a>(&self, _header: &M::Header, _state: &<M as Localized<'a>>::StateContext) -> Result<Vec<u8>, String> { Ok(Vec::new()) }
fn genesis_epoch_data<'a>(&self, _header: &Header, _state: &machine::Call) -> Result<Vec<u8>, String> { Ok(Vec::new()) }
/// Whether an epoch change is signalled at the given header but will require finality.
/// If a change can be enacted immediately then return `No` from this function but
@@ -320,7 +357,7 @@ pub trait Engine<M: Machine>: Sync + Send {
/// Return `Yes` or `No` when the answer is definitively known.
///
/// Should not interact with state.
fn signals_epoch_end<'a>(&self, _header: &M::Header, _aux: <M as Localized<'a>>::AuxiliaryData)
fn signals_epoch_end<'a>(&self, _header: &Header, _aux: AuxiliaryData<'a>)
-> EpochChange<M>
{
EpochChange::No
@@ -336,9 +373,9 @@ pub trait Engine<M: Machine>: Sync + Send {
/// Return optional transition proof.
fn is_epoch_end(
&self,
_chain_head: &M::Header,
_chain_head: &Header,
_finalized: &[H256],
_chain: &Headers<M::Header>,
_chain: &Headers<Header>,
_transition_store: &PendingTransitionStore,
) -> Option<Vec<u8>> {
None
@@ -355,8 +392,8 @@ pub trait Engine<M: Machine>: Sync + Send {
/// Return optional transition proof.
fn is_epoch_end_light(
&self,
_chain_head: &M::Header,
_chain: &Headers<M::Header>,
_chain_head: &Header,
_chain: &Headers<Header>,
_transition_store: &PendingTransitionStore,
) -> Option<Vec<u8>> {
None
@@ -364,22 +401,18 @@ pub trait Engine<M: Machine>: Sync + Send {
/// Create an epoch verifier from validation proof and a flag indicating
/// whether finality is required.
fn epoch_verifier<'a>(&self, _header: &M::Header, _proof: &'a [u8]) -> ConstructedVerifier<'a, M> {
ConstructedVerifier::Trusted(Box::new(self::epoch::NoOp))
fn epoch_verifier<'a>(&self, _header: &Header, _proof: &'a [u8]) -> ConstructedVerifier<'a, M> {
ConstructedVerifier::Trusted(Box::new(NoOp))
}
/// Populate a header's fields based on its parent's header.
/// Usually implements the chain scoring rule based on weight.
fn populate_from_parent(&self, _header: &mut M::Header, _parent: &M::Header) { }
fn populate_from_parent(&self, _header: &mut Header, _parent: &Header) { }
/// Handle any potential consensus messages;
/// updating consensus state and potentially issuing a new one.
fn handle_message(&self, _message: &[u8]) -> Result<(), EngineError> { Err(EngineError::UnexpectedMessage) }
/// Find out if the block is a proposal block and should not be inserted into the DB.
/// Takes a header of a fully verified block.
fn is_proposal(&self, _verified_header: &M::Header) -> bool { false }
/// Register a component which signs consensus messages.
fn set_signer(&self, _signer: Box<EngineSigner>) {}
@@ -393,7 +426,7 @@ pub trait Engine<M: Machine>: Sync + Send {
fn step(&self) {}
/// Stops any services that the may hold the Engine and makes it safe to drop.
fn stop(&self) {}
fn stop(&mut self) {}
/// Create a factory for building snapshot chunks and restoring from them.
/// Returning `None` indicates that this engine doesn't support snapshot creation.
@@ -421,16 +454,21 @@ pub trait Engine<M: Machine>: Sync + Send {
/// Gather all ancestry actions. Called at the last stage when a block is committed. The Engine must guarantee that
/// the ancestry exists.
fn ancestry_actions(&self, _header: &M::Header, _ancestry: &mut Iterator<Item=M::ExtendedHeader>) -> Vec<AncestryAction> {
fn ancestry_actions(&self, _header: &Header, _ancestry: &mut Iterator<Item = ExtendedHeader>) -> Vec<AncestryAction> {
Vec::new()
}
/// Check whether the given new block is the best block, after finalization check.
fn fork_choice(&self, new: &M::ExtendedHeader, best: &M::ExtendedHeader) -> ForkChoice;
fn fork_choice(&self, new: &ExtendedHeader, best: &ExtendedHeader) -> ForkChoice;
/// Returns author should used when executing tx's for this block.
fn executive_author(&self, header: &Header) -> Result<Address, Error> {
Ok(*header.author())
}
}
/// Check whether a given block is the best block based on the default total difficulty rule.
pub fn total_difficulty_fork_choice<T: TotalScoredHeader>(new: &T, best: &T) -> ForkChoice where <T as TotalScoredHeader>::Value: Ord {
pub fn total_difficulty_fork_choice(new: &ExtendedHeader, best: &ExtendedHeader) -> ForkChoice {
if new.total_score() > best.total_score() {
ForkChoice::New
} else {
@@ -523,3 +561,29 @@ pub trait EthEngine: Engine<::machine::EthereumMachine> {
// convenience wrappers for existing functions.
impl<T> EthEngine for T where T: Engine<::machine::EthereumMachine> { }
/// Verifier for all blocks within an epoch with self-contained state.
pub trait EpochVerifier<M: machine::Machine>: Send + Sync {
/// Lightly verify the next block header.
/// This may not be a header belonging to a different epoch.
fn verify_light(&self, header: &Header) -> Result<(), M::Error>;
/// Perform potentially heavier checks on the next block header.
fn verify_heavy(&self, header: &Header) -> Result<(), M::Error> {
self.verify_light(header)
}
/// Check a finality proof against this epoch verifier.
/// Returns `Some(hashes)` if the proof proves finality of these hashes.
/// Returns `None` if the proof doesn't prove anything.
fn check_finality_proof(&self, _proof: &[u8]) -> Option<Vec<H256>> {
None
}
}
/// Special "no-op" verifier for stateless, epoch-less engines.
pub struct NoOp;
impl<M: machine::Machine> EpochVerifier<M> for NoOp {
fn verify_light(&self, _header: &Header) -> Result<(), M::Error> { Ok(()) }
}

View File

@@ -17,9 +17,10 @@
use engines::Engine;
use engines::block_reward::{self, RewardKind};
use ethereum_types::U256;
use machine::WithRewards;
use parity_machine::{Machine, Header, LiveBlock, TotalScoredHeader};
use machine::Machine;
use types::BlockNumber;
use types::header::{Header, ExtendedHeader};
use block::ExecutedBlock;
/// Params for a null engine.
#[derive(Clone, Default)]
@@ -58,26 +59,23 @@ impl<M: Default> Default for NullEngine<M> {
}
}
impl<M: Machine + WithRewards> Engine<M> for NullEngine<M>
where M::ExtendedHeader: TotalScoredHeader,
<M::ExtendedHeader as TotalScoredHeader>::Value: Ord
{
impl<M: Machine> Engine<M> for NullEngine<M> {
fn name(&self) -> &str {
"NullEngine"
}
fn machine(&self) -> &M { &self.machine }
fn on_close_block(&self, block: &mut M::LiveBlock) -> Result<(), M::Error> {
fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), M::Error> {
use std::ops::Shr;
let author = *LiveBlock::header(&*block).author();
let number = LiveBlock::header(&*block).number();
let author = *block.header.author();
let number = block.header.number();
let reward = self.params.block_reward;
if reward == U256::zero() { return Ok(()) }
let n_uncles = LiveBlock::uncles(&*block).len();
let n_uncles = block.uncles.len();
let mut rewards = Vec::new();
@@ -86,7 +84,7 @@ impl<M: Machine + WithRewards> Engine<M> for NullEngine<M>
rewards.push((author, RewardKind::Author, result_block_reward));
// bestow uncle rewards.
for u in LiveBlock::uncles(&*block) {
for u in &block.uncles {
let uncle_author = u.author();
let result_uncle_reward = (reward * U256::from(8 + u.number() - number)).shr(3);
rewards.push((*uncle_author, RewardKind::uncle(number, u.number()), result_uncle_reward));
@@ -97,7 +95,7 @@ impl<M: Machine + WithRewards> Engine<M> for NullEngine<M>
fn maximum_uncle_count(&self, _block: BlockNumber) -> usize { 2 }
fn verify_local_seal(&self, _header: &M::Header) -> Result<(), M::Error> {
fn verify_local_seal(&self, _header: &Header) -> Result<(), M::Error> {
Ok(())
}
@@ -105,7 +103,7 @@ impl<M: Machine + WithRewards> Engine<M> for NullEngine<M>
Some(Box::new(::snapshot::PowSnapshot::new(10000, 10000)))
}
fn fork_choice(&self, new: &M::ExtendedHeader, current: &M::ExtendedHeader) -> super::ForkChoice {
fn fork_choice(&self, new: &ExtendedHeader, current: &ExtendedHeader) -> super::ForkChoice {
super::total_difficulty_fork_choice(new, current)
}
}

View File

@@ -74,7 +74,7 @@ impl Multi {
impl ValidatorSet for Multi {
fn default_caller(&self, block_id: BlockId) -> Box<Call> {
self.correct_set(block_id).map(|set| set.default_caller(block_id))
.unwrap_or(Box::new(|_, _| Err("No validator set for given ID.".into())))
.unwrap_or_else(|| Box::new(|_, _| Err("No validator set for given ID.".into())))
}
fn on_epoch_begin(&self, _first: bool, header: &Header, call: &mut SystemCall) -> Result<(), ::error::Error> {
@@ -141,7 +141,7 @@ impl ValidatorSet for Multi {
*self.block_number.write() = Box::new(move |id| client
.upgrade()
.ok_or_else(|| "No client!".into())
.and_then(|c| c.block_number(id).ok_or("Unknown block".into())));
.and_then(|c| c.block_number(id).ok_or_else(|| "Unknown block".into())));
}
}

View File

@@ -16,6 +16,10 @@
//! General error types for use in ethcore.
// Silence: `use of deprecated item 'std::error::Error::cause': replaced by Error::source, which can support downcasting`
// https://github.com/paritytech/parity-ethereum/issues/10302
#![allow(deprecated)]
use std::{fmt, error};
use std::time::SystemTime;
@@ -33,7 +37,7 @@ use engines::EngineError;
pub use executed::{ExecutionError, CallError};
#[derive(Debug, PartialEq, Clone, Copy, Eq)]
#[derive(Debug, PartialEq, Clone, Eq)]
/// Errors concerning block processing.
pub enum BlockError {
/// Block has too many uncles.
@@ -84,7 +88,7 @@ pub enum BlockError {
/// Timestamp header field is too far in future.
TemporarilyInvalid(OutOfBounds<SystemTime>),
/// Log bloom header field is invalid.
InvalidLogBloom(Mismatch<Bloom>),
InvalidLogBloom(Box<Mismatch<Bloom>>),
/// Number field of header is invalid.
InvalidNumber(Mismatch<BlockNumber>),
/// Block number isn't sensible.

View File

@@ -241,17 +241,16 @@ impl Engine<EthereumMachine> for Arc<Ethash> {
/// This assumes that all uncles are valid uncles (i.e. of at least one generation before the current).
fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> {
use std::ops::Shr;
use parity_machine::LiveBlock;
let author = *LiveBlock::header(&*block).author();
let number = LiveBlock::header(&*block).number();
let author = *block.header.author();
let number = block.header.number();
let rewards = match self.ethash_params.block_reward_contract {
Some(ref c) if number >= self.ethash_params.block_reward_contract_transition => {
let mut beneficiaries = Vec::new();
beneficiaries.push((author, RewardKind::Author));
for u in LiveBlock::uncles(&*block) {
for u in &block.uncles {
let uncle_author = u.author();
beneficiaries.push((*uncle_author, RewardKind::uncle(number, u.number())));
}
@@ -274,7 +273,8 @@ impl Engine<EthereumMachine> for Arc<Ethash> {
let eras_rounds = self.ethash_params.ecip1017_era_rounds;
let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, reward, number);
let n_uncles = LiveBlock::uncles(&*block).len();
//let n_uncles = LiveBlock::uncles(&*block).len();
let n_uncles = block.uncles.len();
// Bestow block rewards.
let mut result_block_reward = reward + reward.shr(5) * U256::from(n_uncles);
@@ -282,7 +282,7 @@ impl Engine<EthereumMachine> for Arc<Ethash> {
rewards.push((author, RewardKind::Author, result_block_reward));
// Bestow uncle rewards.
for u in LiveBlock::uncles(&*block) {
for u in &block.uncles {
let uncle_author = u.author();
let result_uncle_reward = if eras == 0 {
(reward * U256::from(8 + u.number() - number)).shr(3)
@@ -540,9 +540,9 @@ mod tests {
let genesis_header = spec.genesis_header();
let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false, None).unwrap();
let b = b.close().unwrap();
assert_eq!(b.state().balance(&Address::zero()).unwrap(), U256::from_str("4563918244f40000").unwrap());
assert_eq!(b.state.balance(&Address::zero()).unwrap(), U256::from_str("4563918244f40000").unwrap());
}
#[test]
@@ -589,15 +589,15 @@ mod tests {
let genesis_header = spec.genesis_header();
let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let mut b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
let mut b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false, None).unwrap();
let mut uncle = Header::new();
let uncle_author: Address = "ef2d6d194084c2de36e0dabfce45d046b37d1106".into();
uncle.set_author(uncle_author);
b.push_uncle(uncle).unwrap();
let b = b.close().unwrap();
assert_eq!(b.state().balance(&Address::zero()).unwrap(), "478eae0e571ba000".into());
assert_eq!(b.state().balance(&uncle_author).unwrap(), "3cb71f51fc558000".into());
assert_eq!(b.state.balance(&Address::zero()).unwrap(), "478eae0e571ba000".into());
assert_eq!(b.state.balance(&uncle_author).unwrap(), "3cb71f51fc558000".into());
}
#[test]
@@ -607,14 +607,14 @@ mod tests {
let genesis_header = spec.genesis_header();
let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap();
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false, None).unwrap();
let b = b.close().unwrap();
let ubi_contract: Address = "00efdd5883ec628983e9063c7d969fe268bbf310".into();
let dev_contract: Address = "00756cf8159095948496617f5fb17ed95059f536".into();
assert_eq!(b.state().balance(&Address::zero()).unwrap(), U256::from_str("d8d726b7177a80000").unwrap());
assert_eq!(b.state().balance(&ubi_contract).unwrap(), U256::from_str("2b5e3af16b1880000").unwrap());
assert_eq!(b.state().balance(&dev_contract).unwrap(), U256::from_str("c249fdd327780000").unwrap());
assert_eq!(b.state.balance(&Address::zero()).unwrap(), U256::from_str("d8d726b7177a80000").unwrap());
assert_eq!(b.state.balance(&ubi_contract).unwrap(), U256::from_str("2b5e3af16b1880000").unwrap());
assert_eq!(b.state.balance(&dev_contract).unwrap(), U256::from_str("c249fdd327780000").unwrap());
}
#[test]

View File

@@ -79,21 +79,16 @@ pub fn new_ellaism<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/ellaism.json"))
}
/// Create a new Easthub mainnet chain spec.
pub fn new_easthub<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/easthub.json"))
}
/// Create a new Ethereum Social mainnet chain spec.
pub fn new_social<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/social.json"))
}
/// Create a new MIX mainnet chain spec.
pub fn new_mix<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/mix.json"))
}
/// Create a new Callisto chain spec
pub fn new_callisto<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/callisto.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"))
@@ -109,16 +104,26 @@ pub fn new_kovan<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/kovan.json"))
}
/// Create a new Rinkeby testnet chain spec.
pub fn new_rinkeby<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/rinkeby.json"))
}
/// Create a new Görli testnet chain spec.
pub fn new_goerli<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/goerli.json"))
}
/// Create a new Kotti testnet chain spec.
pub fn new_kotti<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/kotti.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"))
}
/// Create a new Callisto chaun spec
pub fn new_callisto<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/callisto.json"))
}
// For tests
/// Create a new Foundation Frontier-era chain spec as though it never changes to Homestead.

View File

@@ -167,7 +167,7 @@ pub enum CallError {
/// Couldn't find requested block's state in the chain.
StatePruned,
/// Couldn't find an amount of gas that didn't result in an exception.
Exceptional,
Exceptional(vm::Error),
/// Corrupt state.
StateCorrupt,
/// Error executing.
@@ -187,7 +187,7 @@ impl fmt::Display for CallError {
let msg = match *self {
TransactionNotFound => "Transaction couldn't be found in the chain".into(),
StatePruned => "Couldn't find the transaction block's state in the chain".into(),
Exceptional => "An exception happened in the execution".into(),
Exceptional(ref e) => format!("An exception ({}) happened in the execution", e),
StateCorrupt => "Stored state found to be corrupted.".into(),
Execution(ref e) => format!("{}", e),
};
@@ -197,4 +197,4 @@ impl fmt::Display for CallError {
}
/// Transaction execution result.
pub type ExecutionResult = Result<Executed, ExecutionError>;
pub type ExecutionResult = Result<Box<Executed>, ExecutionError>;

View File

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

View File

@@ -18,7 +18,7 @@ use std::path::Path;
use super::test_common::*;
use pod_state::PodState;
use trace;
use client::{EvmTestClient, EvmTestError, TransactResult};
use client::{EvmTestClient, EvmTestError, TransactErr, TransactSuccess};
use ethjson;
use types::transaction::SignedTransaction;
use vm::EnvInfo;
@@ -90,18 +90,18 @@ pub fn json_chain_test<H: FnMut(&str, HookType)>(json_data: &[u8], start_stop_ho
flushln!("{} fail", info);
failed.push(name.clone());
},
Ok(TransactResult::Ok { state_root, .. }) if state_root != post_root => {
Ok(Ok(TransactSuccess { state_root, .. })) if state_root != post_root => {
println!("{} !!! State mismatch (got: {}, expect: {}", info, state_root, post_root);
flushln!("{} fail", info);
failed.push(name.clone());
},
Ok(TransactResult::Err { state_root, ref error, .. }) if state_root != post_root => {
Ok(Err(TransactErr { state_root, ref error, .. })) if state_root != post_root => {
println!("{} !!! State mismatch (got: {}, expect: {}", info, state_root, post_root);
println!("{} !!! Execution error: {:?}", info, error);
flushln!("{} fail", info);
failed.push(name.clone());
},
Ok(TransactResult::Err { error, .. }) => {
Ok(Err(TransactErr { error, .. })) => {
flushln!("{} ok ({:?})", info, error);
},
Ok(_) => {

View File

@@ -90,7 +90,6 @@ extern crate num;
extern crate num_cpus;
extern crate parity_bytes as bytes;
extern crate parity_crypto;
extern crate parity_machine;
extern crate parity_snappy as snappy;
extern crate parking_lot;
extern crate trie_db as trie;

View File

@@ -24,11 +24,11 @@ use ethereum_types::{U256, H256, Address};
use rlp::Rlp;
use types::transaction::{self, SYSTEM_ADDRESS, UNSIGNED_SENDER, UnverifiedTransaction, SignedTransaction};
use types::BlockNumber;
use types::header::{Header, ExtendedHeader};
use types::header::Header;
use vm::{CallType, ActionParams, ActionValue, ParamsType};
use vm::{EnvInfo, Schedule, CreateContractAddress};
use block::{ExecutedBlock, IsBlock};
use block::ExecutedBlock;
use builtin::Builtin;
use call_contract::CallContract;
use client::BlockInfo;
@@ -36,7 +36,7 @@ use error::Error;
use executive::Executive;
use spec::CommonParams;
use state::{CleanupMode, Substate};
use trace::{NoopTracer, NoopVMTracer, Tracer, ExecutiveTracer, RewardType, Tracing};
use trace::{NoopTracer, NoopVMTracer};
use tx_filter::TransactionFilter;
/// Parity tries to round block.gas_limit to multiple of this constant
@@ -126,7 +126,7 @@ impl EthereumMachine {
data: Option<Vec<u8>>,
) -> Result<Vec<u8>, Error> {
let (code, code_hash) = {
let state = block.state();
let state = &block.state;
(state.code(&contract_address)?,
state.code_hash(&contract_address)?)
@@ -173,7 +173,7 @@ impl EthereumMachine {
origin: SYSTEM_ADDRESS,
gas,
gas_price: 0.into(),
value: value.unwrap_or(ActionValue::Transfer(0.into())),
value: value.unwrap_or_else(|| ActionValue::Transfer(0.into())),
code,
code_hash,
data,
@@ -193,12 +193,12 @@ impl EthereumMachine {
/// Push last known block hash to the state.
fn push_last_hash(&self, block: &mut ExecutedBlock) -> Result<(), Error> {
let params = self.params();
if block.header().number() == params.eip210_transition {
if block.header.number() == params.eip210_transition {
let state = block.state_mut();
state.init_code(&params.eip210_contract_address, params.eip210_contract_code.clone())?;
}
if block.header().number() >= params.eip210_transition {
let parent_hash = block.header().parent_hash().clone();
if block.header.number() >= params.eip210_transition {
let parent_hash = *block.header.parent_hash();
let _ = self.execute_as_system(
block,
params.eip210_contract_address,
@@ -215,7 +215,7 @@ impl EthereumMachine {
self.push_last_hash(block)?;
if let Some(ref ethash_params) = self.ethash_extensions {
if block.header().number() == ethash_params.dao_hardfork_transition {
if block.header.number() == ethash_params.dao_hardfork_transition {
let state = block.state_mut();
for child in &ethash_params.dao_hardfork_accounts {
let beneficiary = &ethash_params.dao_hardfork_beneficiary;
@@ -428,19 +428,13 @@ pub enum AuxiliaryRequest {
Both,
}
impl ::parity_machine::Machine for EthereumMachine {
type Header = Header;
type ExtendedHeader = ExtendedHeader;
type LiveBlock = ExecutedBlock;
impl super::Machine for EthereumMachine {
type EngineClient = ::client::EngineClient;
type AuxiliaryRequest = AuxiliaryRequest;
type AncestryAction = ::types::ancestry_action::AncestryAction;
type Error = Error;
fn balance(&self, live: &ExecutedBlock, address: &Address) -> Result<U256, Error> {
live.state().balance(address).map_err(Into::into)
live.state.balance(address).map_err(Into::into)
}
fn add_balance(&self, live: &mut ExecutedBlock, address: &Address, amount: &U256) -> Result<(), Error> {
@@ -448,42 +442,6 @@ impl ::parity_machine::Machine for EthereumMachine {
}
}
impl<'a> ::parity_machine::LocalizedMachine<'a> for EthereumMachine {
type StateContext = Call<'a>;
type AuxiliaryData = AuxiliaryData<'a>;
}
/// A state machine that uses block rewards.
pub trait WithRewards: ::parity_machine::Machine {
/// Note block rewards, traces each reward storing information about benefactor, amount and type
/// of reward.
fn note_rewards(
&self,
live: &mut Self::LiveBlock,
rewards: &[(Address, RewardType, U256)],
) -> Result<(), Self::Error>;
}
impl WithRewards for EthereumMachine {
fn note_rewards(
&self,
live: &mut Self::LiveBlock,
rewards: &[(Address, RewardType, U256)],
) -> Result<(), Self::Error> {
if let Tracing::Enabled(ref mut traces) = *live.traces_mut() {
let mut tracer = ExecutiveTracer::default();
for &(address, ref reward_type, amount) in rewards {
tracer.trace_reward(address, amount, reward_type.clone());
}
traces.push(tracer.drain().into());
}
Ok(())
}
}
// Try to round gas_limit a bit so that:
// 1) it will still be in desired range
// 2) it will be a nearest (with tendency to increase) multiple of PARITY_GAS_LIMIT_DETERMINANT

View File

@@ -0,0 +1,7 @@
//! Generalization of a state machine for a consensus engine.
mod impls;
mod traits;
pub use self::impls::*;
pub use self::traits::*;

View File

@@ -0,0 +1,37 @@
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.
// Parity Ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
//! Generalization of a state machine for a consensus engine.
//! This will define traits for the header, block, and state of a blockchain.
use ethereum_types::{U256, Address};
use block::ExecutedBlock;
/// Generalization of types surrounding blockchain-suitable state machines.
pub trait Machine: Send + Sync {
/// A handle to a blockchain client for this machine.
type EngineClient: ?Sized;
/// Errors which can occur when querying or interacting with the machine.
type Error;
/// Get the balance, in base units, associated with an account.
/// Extracts data from the live block.
fn balance(&self, live: &ExecutedBlock, address: &Address) -> Result<U256, Self::Error>;
/// Increment the balance of an account in the state of the live block.
fn add_balance(&self, live: &mut ExecutedBlock, address: &Address, amount: &U256) -> Result<(), Self::Error>;
}

View File

@@ -25,6 +25,7 @@ use call_contract::CallContract;
use ethcore_miner::gas_pricer::GasPricer;
use ethcore_miner::local_accounts::LocalAccounts;
use ethcore_miner::pool::{self, TransactionQueue, VerifiedTransaction, QueueStatus, PrioritizationStrategy};
use ethcore_miner::service_transaction_checker::ServiceTransactionChecker;
#[cfg(feature = "work-notify")]
use ethcore_miner::work_notify::NotifyWork;
use ethereum_types::{H256, U256, Address};
@@ -46,7 +47,7 @@ use types::header::Header;
use types::receipt::RichReceipt;
use using_queue::{UsingQueue, GetAction};
use block::{ClosedBlock, IsBlock, SealedBlock};
use block::{ClosedBlock, SealedBlock};
use client::{
BlockChain, ChainInfo, BlockProducer, SealedBlockImporter, Nonce, TransactionInfo, TransactionId
};
@@ -214,7 +215,6 @@ impl Author {
}
}
struct SealingWork {
queue: UsingQueue<ClosedBlock>,
enabled: bool,
@@ -247,6 +247,7 @@ pub struct Miner {
engine: Arc<EthEngine>,
accounts: Arc<LocalAccounts>,
io_channel: RwLock<Option<IoChannel<ClientIoMessage>>>,
service_transaction_checker: Option<ServiceTransactionChecker>,
}
impl Miner {
@@ -273,6 +274,7 @@ impl Miner {
let verifier_options = options.pool_verification_options.clone();
let tx_queue_strategy = options.tx_queue_strategy;
let nonce_cache_size = cmp::max(4096, limits.max_count / 4);
let refuse_service_transactions = options.refuse_service_transactions;
Miner {
sealing: Mutex::new(SealingWork {
@@ -293,6 +295,11 @@ impl Miner {
accounts: Arc::new(accounts),
engine: spec.engine.clone(),
io_channel: RwLock::new(None),
service_transaction_checker: if refuse_service_transactions {
None
} else {
Some(ServiceTransactionChecker::default())
},
}
}
@@ -351,6 +358,11 @@ impl Miner {
});
}
/// Returns ServiceTransactionChecker
pub fn service_transaction_checker(&self) -> Option<ServiceTransactionChecker> {
self.service_transaction_checker.clone()
}
/// 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.
@@ -362,7 +374,7 @@ impl Miner {
.and_then(|b| {
// 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 {
if b.header.number() >= latest_block_number {
Some(f(b))
} else {
None
@@ -378,7 +390,7 @@ impl Miner {
&self.nonce_cache,
&*self.engine,
&*self.accounts,
self.options.refuse_service_transactions,
self.service_transaction_checker.as_ref(),
)
}
@@ -392,7 +404,7 @@ impl Miner {
// Open block
let (mut open_block, original_work_hash) = {
let mut sealing = self.sealing.lock();
let last_work_hash = sealing.queue.peek_last_ref().map(|pb| pb.block().header().hash());
let last_work_hash = sealing.queue.peek_last_ref().map(|pb| pb.header.hash());
let best_hash = chain_info.best_block_hash;
// check to see if last ClosedBlock in would_seals is actually same parent block.
@@ -401,7 +413,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.get_pending_if(|b| b.block().header().parent_hash() == &best_hash) {
let mut open_block = match sealing.queue.get_pending_if(|b| b.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
@@ -436,7 +448,7 @@ impl Miner {
let mut invalid_transactions = HashSet::new();
let mut not_allowed_transactions = HashSet::new();
let mut senders_to_penalize = HashSet::new();
let block_number = open_block.block().header().number();
let block_number = open_block.header.number();
let mut tx_count = 0usize;
let mut skipped_transactions = 0usize;
@@ -453,7 +465,7 @@ impl Miner {
let max_transactions = if min_tx_gas.is_zero() {
usize::max_value()
} else {
MAX_SKIPPED_TRANSACTIONS.saturating_add(cmp::min(*open_block.block().header().gas_limit() / min_tx_gas, u64::max_value().into()).as_u64() as usize)
MAX_SKIPPED_TRANSACTIONS.saturating_add(cmp::min(*open_block.header.gas_limit() / min_tx_gas, u64::max_value().into()).as_u64() as usize)
};
let pending: Vec<Arc<_>> = self.transaction_queue.pending(
@@ -630,13 +642,16 @@ impl Miner {
}
}
/// Attempts to perform internal sealing (one that does not require work) and handles the result depending on the type of Seal.
// TODO: (https://github.com/paritytech/parity-ethereum/issues/10407)
// This is only used in authority_round path, and should be refactored to merge with the other seal() path.
// Attempts to perform internal sealing (one that does not require work) and handles the result depending on the
// type of Seal.
fn seal_and_import_block_internally<C>(&self, chain: &C, block: ClosedBlock) -> bool
where C: BlockChain + SealedBlockImporter,
{
{
let sealing = self.sealing.lock();
if block.transactions().is_empty()
if block.transactions.is_empty()
&& !self.forced_sealing()
&& Instant::now() <= sealing.next_mandatory_reseal
{
@@ -646,7 +661,7 @@ impl Miner {
trace!(target: "miner", "seal_block_internally: attempting internal seal.");
let parent_header = match chain.block_header(BlockId::Hash(*block.header().parent_hash())) {
let parent_header = match chain.block_header(BlockId::Hash(*block.header.parent_hash())) {
Some(h) => {
match h.decode() {
Ok(decoded_hdr) => decoded_hdr,
@@ -656,7 +671,7 @@ impl Miner {
None => return false,
};
match self.engine.generate_seal(block.block(), &parent_header) {
match self.engine.generate_seal(&block, &parent_header) {
// Save proposal for later seal submission and broadcast it.
Seal::Proposal(seal) => {
trace!(target: "miner", "Received a Proposal seal.");
@@ -705,11 +720,11 @@ impl Miner {
/// Prepares work which has to be done to seal.
fn prepare_work(&self, block: ClosedBlock, original_work_hash: Option<H256>) {
let (work, is_new) = {
let block_header = block.block().header().clone();
let block_header = block.header.clone();
let block_hash = block_header.hash();
let mut sealing = self.sealing.lock();
let last_work_hash = sealing.queue.peek_last_ref().map(|pb| pb.block().header().hash());
let last_work_hash = sealing.queue.peek_last_ref().map(|pb| pb.header.hash());
trace!(
target: "miner",
@@ -742,7 +757,7 @@ impl Miner {
trace!(
target: "miner",
"prepare_work: leaving (last={:?})",
sealing.queue.peek_last_ref().map(|b| b.block().header().hash())
sealing.queue.peek_last_ref().map(|b| b.header.hash())
);
(work, is_new)
};
@@ -994,7 +1009,7 @@ impl miner::MinerService for Miner {
let from_pending = || {
self.map_existing_pending_block(|sealing| {
sealing.transactions()
sealing.transactions
.iter()
.map(|signed| signed.hash())
.collect()
@@ -1041,7 +1056,7 @@ impl miner::MinerService for Miner {
let from_pending = || {
self.map_existing_pending_block(|sealing| {
sealing.transactions()
sealing.transactions
.iter()
.map(|signed| pool::VerifiedTransaction::from_pending_block_transaction(signed.clone()))
.map(Arc::new)
@@ -1086,9 +1101,9 @@ impl miner::MinerService for Miner {
fn pending_receipts(&self, best_block: BlockNumber) -> Option<Vec<RichReceipt>> {
self.map_existing_pending_block(|pending| {
let receipts = pending.receipts();
pending.transactions()
.into_iter()
let receipts = &pending.receipts;
pending.transactions
.iter()
.enumerate()
.map(|(index, tx)| {
let prev_gas = if index == 0 { Default::default() } else { receipts[index - 1].gas_used };
@@ -1102,7 +1117,7 @@ impl miner::MinerService for Miner {
Action::Call(_) => None,
Action::Create => {
let sender = tx.sender();
Some(contract_address(self.engine.create_address_scheme(pending.header().number()), &sender, &tx.nonce, &tx.data).0)
Some(contract_address(self.engine.create_address_scheme(pending.header.number()), &sender, &tx.nonce, &tx.data).0)
}
},
logs: receipt.logs.clone(),
@@ -1139,10 +1154,10 @@ 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 {
if 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);
on by default. Please remove these forks and start your chain again: {}.", name);
return;
}
}
@@ -1180,7 +1195,7 @@ impl miner::MinerService for Miner {
self.prepare_pending_block(chain);
self.sealing.lock().queue.use_last_ref().map(|b| {
let header = b.header();
let header = &b.header;
(header.hash(), header.number(), header.timestamp(), *header.difficulty())
})
}
@@ -1194,9 +1209,9 @@ impl miner::MinerService for Miner {
} else {
GetAction::Take
},
|b| &b.hash() == &block_hash
|b| &b.header.bare_hash() == &block_hash
) {
trace!(target: "miner", "Submitted block {}={}={} with seal {:?}", block_hash, b.hash(), b.header().bare_hash(), seal);
trace!(target: "miner", "Submitted block {}={} with seal {:?}", block_hash, b.header.bare_hash(), seal);
b.lock().try_seal(&*self.engine, seal).or_else(|e| {
warn!(target: "miner", "Mined solution rejected: {}", e);
Err(ErrorKind::PowInvalid.into())
@@ -1207,8 +1222,8 @@ impl miner::MinerService for Miner {
};
result.and_then(|sealed| {
let n = sealed.header().number();
let h = sealed.header().hash();
let n = sealed.header.number();
let h = sealed.header.hash();
info!(target: "miner", "Submitted block imported OK. #{}: {}", Colour::White.bold().paint(format!("{}", n)), Colour::White.bold().paint(format!("{:x}", h)));
Ok(sealed)
})
@@ -1281,7 +1296,7 @@ impl miner::MinerService for Miner {
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 service_transaction_checker = self.service_transaction_checker.clone();
let cull = move |chain: &::client::Client| {
let client = PoolClient::new(
@@ -1289,7 +1304,7 @@ impl miner::MinerService for Miner {
&nonce_cache,
&*engine,
&*accounts,
refuse_service_transactions,
service_transaction_checker.as_ref(),
);
queue.cull(client);
};
@@ -1301,22 +1316,39 @@ impl miner::MinerService for Miner {
self.transaction_queue.cull(client);
}
}
if let Some(ref service_transaction_checker) = self.service_transaction_checker {
match service_transaction_checker.refresh_cache(chain) {
Ok(true) => {
trace!(target: "client", "Service transaction cache was refreshed successfully");
},
Ok(false) => {
trace!(target: "client", "Registrar or/and service transactions contract does not exist");
},
Err(e) => error!(target: "client", "Error occurred while refreshing service transaction cache: {}", e)
};
};
}
fn pending_state(&self, latest_block_number: BlockNumber) -> Option<Self::State> {
self.map_existing_pending_block(|b| b.state().clone(), latest_block_number)
self.map_existing_pending_block(|b| b.state.clone(), latest_block_number)
}
fn pending_block_header(&self, latest_block_number: BlockNumber) -> Option<Header> {
self.map_existing_pending_block(|b| b.header().clone(), latest_block_number)
self.map_existing_pending_block(|b| b.header.clone(), latest_block_number)
}
fn pending_block(&self, latest_block_number: BlockNumber) -> Option<Block> {
self.map_existing_pending_block(|b| b.to_base(), latest_block_number)
self.map_existing_pending_block(|b| {
Block {
header: b.header.clone(),
transactions: b.transactions.iter().cloned().map(Into::into).collect(),
uncles: b.uncles.to_vec(),
}
}, latest_block_number)
}
fn pending_transactions(&self, latest_block_number: BlockNumber) -> Option<Vec<SignedTransaction>> {
self.map_existing_pending_block(|b| b.transactions().into_iter().cloned().collect(), latest_block_number)
self.map_existing_pending_block(|b| b.transactions.iter().cloned().collect(), latest_block_number)
}
}

View File

@@ -75,7 +75,7 @@ pub struct PoolClient<'a, C: 'a> {
engine: &'a EthEngine,
accounts: &'a LocalAccounts,
best_block_header: Header,
service_transaction_checker: Option<ServiceTransactionChecker>,
service_transaction_checker: Option<&'a ServiceTransactionChecker>,
}
impl<'a, C: 'a> Clone for PoolClient<'a, C> {
@@ -100,7 +100,7 @@ impl<'a, C: 'a> PoolClient<'a, C> where
cache: &'a NonceCache,
engine: &'a EthEngine,
accounts: &'a LocalAccounts,
refuse_service_transactions: bool,
service_transaction_checker: Option<&'a ServiceTransactionChecker>,
) -> Self {
let best_block_header = chain.best_block_header();
PoolClient {
@@ -109,11 +109,7 @@ impl<'a, C: 'a> PoolClient<'a, C> where
engine,
accounts,
best_block_header,
service_transaction_checker: if refuse_service_transactions {
None
} else {
Some(Default::default())
},
service_transaction_checker,
}
}

View File

@@ -76,7 +76,7 @@ impl SnapshotComponents for PoaSnapshot {
}
let header = chain.block_header_data(&transition.block_hash)
.ok_or(Error::BlockNotFound(transition.block_hash))?;
.ok_or_else(|| Error::BlockNotFound(transition.block_hash))?;
let entry = {
let mut entry_stream = RlpStream::new_list(2);
@@ -101,12 +101,12 @@ impl SnapshotComponents for PoaSnapshot {
let (block, receipts) = chain.block(&block_at)
.and_then(|b| chain.block_receipts(&block_at).map(|r| (b, r)))
.ok_or(Error::BlockNotFound(block_at))?;
.ok_or_else(|| Error::BlockNotFound(block_at))?;
let block = block.decode()?;
let parent_td = chain.block_details(block.header.parent_hash())
.map(|d| d.total_difficulty)
.ok_or(Error::BlockNotFound(block_at))?;
.ok_or_else(|| Error::BlockNotFound(block_at))?;
rlps.push({
let mut stream = RlpStream::new_list(5);

View File

@@ -116,7 +116,7 @@ impl<'a> PowWorker<'a> {
let (block, receipts) = self.chain.block(&self.current_hash)
.and_then(|b| self.chain.block_receipts(&self.current_hash).map(|r| (b, r)))
.ok_or(Error::BlockNotFound(self.current_hash))?;
.ok_or_else(|| Error::BlockNotFound(self.current_hash))?;
let abridged_rlp = AbridgedBlock::from_block_view(&block.view()).into_inner();
@@ -160,7 +160,7 @@ impl<'a> PowWorker<'a> {
let (last_header, last_details) = self.chain.block_header_data(&last)
.and_then(|n| self.chain.block_details(&last).map(|d| (n, d)))
.ok_or(Error::BlockNotFound(last))?;
.ok_or_else(|| Error::BlockNotFound(last))?;
let parent_number = last_header.number() - 1;
let parent_hash = last_header.parent_hash();

View File

@@ -157,7 +157,7 @@ pub fn take_snapshot<W: SnapshotWriter + Send>(
processing_threads: usize,
) -> Result<(), Error> {
let start_header = chain.block_header_data(&block_at)
.ok_or(Error::InvalidStartingBlock(BlockId::Hash(block_at)))?;
.ok_or_else(|| Error::InvalidStartingBlock(BlockId::Hash(block_at)))?;
let state_root = start_header.state_root();
let number = start_header.number();
@@ -512,7 +512,7 @@ fn rebuild_accounts(
// fill out the storage trie and code while decoding.
let (acc, maybe_code) = {
let mut acct_db = AccountDBMut::from_hash(db, hash);
let storage_root = known_storage_roots.get(&hash).cloned().unwrap_or(H256::zero());
let storage_root = known_storage_roots.get(&hash).cloned().unwrap_or_default();
account::from_fat_rlp(&mut acct_db, fat_rlp, storage_root)?
};

View File

@@ -35,7 +35,7 @@ use vm::{EnvInfo, CallType, ActionValue, ActionParams, ParamsType};
use builtin::Builtin;
use engines::{
EthEngine, NullEngine, InstantSeal, InstantSealParams, BasicAuthority,
EthEngine, NullEngine, InstantSeal, InstantSealParams, BasicAuthority, Clique,
AuthorityRound, DEFAULT_BLOCKHASH_CONTRACT
};
use error::Error;
@@ -99,9 +99,9 @@ pub struct CommonParams {
pub validate_receipts_transition: BlockNumber,
/// Validate transaction chain id.
pub validate_chain_id_transition: BlockNumber,
/// Number of first block where EIP-140 (Metropolis: REVERT opcode) rules begin.
/// Number of first block where EIP-140 rules begin.
pub eip140_transition: BlockNumber,
/// Number of first block where EIP-210 (Metropolis: BLOCKHASH changes) rules begin.
/// Number of first block where EIP-210 rules begin.
pub eip210_transition: BlockNumber,
/// EIP-210 Blockhash contract address.
pub eip210_contract_address: Address,
@@ -109,8 +109,7 @@ pub struct CommonParams {
pub eip210_contract_code: Bytes,
/// Gas allocated for EIP-210 blockhash update.
pub eip210_contract_gas: U256,
/// Number of first block where EIP-211 (Metropolis: RETURNDATASIZE/RETURNDATACOPY) rules
/// begin.
/// Number of first block where EIP-211 rules begin.
pub eip211_transition: BlockNumber,
/// Number of first block where EIP-214 rules begin.
pub eip214_transition: BlockNumber,
@@ -515,7 +514,7 @@ fn load_from(spec_params: SpecParams, s: ethjson::spec::Spec) -> Result<Spec, Er
chts: s.hardcoded_sync
.as_ref()
.map(|s| s.chts.iter().map(|c| c.clone().into()).collect())
.unwrap_or(Vec::new()),
.unwrap_or_default()
})
} else {
None
@@ -611,6 +610,8 @@ impl Spec {
ethjson::spec::Engine::InstantSeal(Some(instant_seal)) => Arc::new(InstantSeal::new(instant_seal.params.into(), machine)),
ethjson::spec::Engine::InstantSeal(None) => Arc::new(InstantSeal::new(InstantSealParams::default(), machine)),
ethjson::spec::Engine::BasicAuthority(basic_authority) => Arc::new(BasicAuthority::new(basic_authority.params.into(), machine)),
ethjson::spec::Engine::Clique(clique) => Clique::new(clique.params.into(), machine)
.expect("Failed to start Clique consensus engine."),
ethjson::spec::Engine::AuthorityRound(authority_round) => AuthorityRound::new(authority_round.params.into(), machine)
.expect("Failed to start AuthorityRound consensus engine."),
}
@@ -827,7 +828,6 @@ impl Spec {
ethjson::spec::Spec::load(reader)
.map_err(fmt_err)
.map(load_machine_from)
}
/// Loads spec from json file. Provide factories for executing contracts and ensuring
@@ -999,7 +999,6 @@ mod tests {
use types::view;
use types::views::BlockView;
// https://github.com/paritytech/parity-ethereum/issues/1840
#[test]
fn test_load_empty() {
let tempdir = TempDir::new("").unwrap();

View File

@@ -741,11 +741,4 @@ mod tests {
assert_eq!(a.code_hash(), KECCAK_EMPTY);
assert_eq!(a.storage_root().unwrap(), KECCAK_NULL_RLP);
}
#[test]
fn create_account() {
let a = Account::new(69u8.into(), 0u8.into(), HashMap::new(), Bytes::new());
assert_eq!(a.rlp().to_hex(), "f8448045a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470");
}
}

View File

@@ -82,8 +82,8 @@ pub enum ProvedExecution {
BadProof,
/// The transaction failed, but not due to a bad proof.
Failed(ExecutionError),
/// The transaction successfully completd with the given proof.
Complete(Executed),
/// The transaction successfully completed with the given proof.
Complete(Box<Executed>),
}
#[derive(Eq, PartialEq, Clone, Copy, Debug)]
@@ -218,7 +218,7 @@ pub fn check_proof(
let options = TransactOptions::with_no_tracing().save_output_from_contract();
match state.execute(env_info, machine, transaction, options, true) {
Ok(executed) => ProvedExecution::Complete(executed),
Ok(executed) => ProvedExecution::Complete(Box::new(executed)),
Err(ExecutionError::Internal(_)) => ProvedExecution::BadProof,
Err(e) => ProvedExecution::Failed(e),
}
@@ -1254,7 +1254,7 @@ impl<B: Backend> State<B> {
let trie = TrieDB::new(db, &self.root)?;
let maybe_account: Option<BasicAccount> = {
let panicky_decoder = |bytes: &[u8]| {
::rlp::decode(bytes).expect(&format!("prove_account, could not query trie for account key={}", &account_key))
::rlp::decode(bytes).unwrap_or_else(|_| panic!("prove_account, could not query trie for account key={}", &account_key))
};
let query = (&mut recorder, panicky_decoder);
trie.get_with(&account_key, query)?

View File

@@ -155,7 +155,7 @@ pub fn generate_dummy_client_with_spec_and_data<F>(test_spec: F, block_number: u
(3141562.into(), 31415620.into()),
vec![],
false,
&mut Vec::new().into_iter(),
None,
).unwrap();
rolling_timestamp += 10;
b.set_timestamp(rolling_timestamp);

View File

@@ -27,8 +27,7 @@ use types::filter::Filter;
use types::view;
use types::views::BlockView;
use block::IsBlock;
use client::{BlockChainClient, Client, ClientConfig, BlockId, ChainInfo, BlockInfo, PrepareOpenBlock, ImportSealedBlock, ImportBlock};
use client::{BlockChainClient, BlockChainReset, Client, ClientConfig, BlockId, ChainInfo, BlockInfo, PrepareOpenBlock, ImportSealedBlock, ImportBlock};
use ethereum;
use executive::{Executive, TransactOptions};
use miner::{Miner, PendingOrdering, MinerService};
@@ -254,7 +253,7 @@ fn can_mine() {
let b = client.prepare_open_block(Address::default(), (3141562.into(), 31415620.into()), vec![]).unwrap().close().unwrap();
assert_eq!(*b.block().header().parent_hash(), view!(BlockView, &dummy_blocks[0]).header_view().hash());
assert_eq!(*b.header.parent_hash(), view!(BlockView, &dummy_blocks[0]).header_view().hash());
}
#[test]
@@ -367,3 +366,23 @@ fn transaction_proof() {
assert_eq!(state.balance(&Address::default()).unwrap(), 5.into());
assert_eq!(state.balance(&address).unwrap(), 95.into());
}
#[test]
fn reset_blockchain() {
let client = get_test_client_with_blocks(get_good_dummy_block_seq(19));
// 19 + genesis block
assert!(client.block_header(BlockId::Number(20)).is_some());
assert_eq!(client.block_header(BlockId::Number(20)).unwrap().hash(), client.best_block_header().hash());
assert!(client.reset(5).is_ok());
client.chain().clear_cache();
assert!(client.block_header(BlockId::Number(20)).is_none());
assert!(client.block_header(BlockId::Number(19)).is_none());
assert!(client.block_header(BlockId::Number(18)).is_none());
assert!(client.block_header(BlockId::Number(17)).is_none());
assert!(client.block_header(BlockId::Number(16)).is_none());
assert!(client.block_header(BlockId::Number(15)).is_some());
}

View File

@@ -86,7 +86,7 @@ fn can_trace_block_and_uncle_reward() {
(3141562.into(), 31415620.into()),
vec![],
false,
&mut Vec::new().into_iter(),
None,
).unwrap();
rolling_timestamp += 10;
root_block.set_timestamp(rolling_timestamp);
@@ -115,7 +115,7 @@ fn can_trace_block_and_uncle_reward() {
(3141562.into(), 31415620.into()),
vec![],
false,
&mut Vec::new().into_iter(),
None,
).unwrap();
rolling_timestamp += 10;
parent_block.set_timestamp(rolling_timestamp);
@@ -143,7 +143,7 @@ fn can_trace_block_and_uncle_reward() {
(3141562.into(), 31415620.into()),
vec![],
false,
&mut Vec::new().into_iter(),
None,
).unwrap();
rolling_timestamp += 10;
block.set_timestamp(rolling_timestamp);

View File

@@ -135,7 +135,7 @@ impl Create {
}
/// Reward type.
#[derive(Debug, PartialEq, Clone)]
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum RewardType {
/// Block
Block,

View File

@@ -34,7 +34,7 @@ use unexpected::{Mismatch, OutOfBounds};
use blockchain::*;
use call_contract::CallContract;
use client::BlockInfo;
use engines::EthEngine;
use engines::{EthEngine, MAX_UNCLE_AGE};
use error::{BlockError, Error};
use types::{BlockNumber, header::Header};
use types::transaction::SignedTransaction;
@@ -176,7 +176,7 @@ fn verify_uncles(block: &PreverifiedBlock, bc: &BlockProvider, engine: &EthEngin
excluded.insert(header.hash());
let mut hash = header.parent_hash().clone();
excluded.insert(hash.clone());
for _ in 0..engine.maximum_uncle_age() {
for _ in 0..MAX_UNCLE_AGE {
match bc.block_details(&hash) {
Some(details) => {
excluded.insert(details.parent);
@@ -209,7 +209,7 @@ fn verify_uncles(block: &PreverifiedBlock, bc: &BlockProvider, engine: &EthEngin
// (8 Invalid)
let depth = if header.number() > uncle.number() { header.number() - uncle.number() } else { 0 };
if depth > engine.maximum_uncle_age() as u64 {
if depth > MAX_UNCLE_AGE as u64 {
return Err(From::from(BlockError::UncleTooOld(OutOfBounds { min: Some(header.number() - depth), max: Some(header.number() - 1), found: uncle.number() })));
}
else if depth < 1 {
@@ -258,7 +258,7 @@ pub fn verify_block_final(expected: &Header, got: &Header) -> Result<(), Error>
return Err(From::from(BlockError::InvalidGasUsed(Mismatch { expected: *expected.gas_used(), found: *got.gas_used() })))
}
if expected.log_bloom() != got.log_bloom() {
return Err(From::from(BlockError::InvalidLogBloom(Mismatch { expected: *expected.log_bloom(), found: *got.log_bloom() })))
return Err(From::from(BlockError::InvalidLogBloom(Box::new(Mismatch { expected: *expected.log_bloom(), found: *got.log_bloom() }))))
}
if expected.receipts_root() != got.receipts_root() {
return Err(From::from(BlockError::InvalidReceiptsRoot(Mismatch { expected: *expected.receipts_root(), found: *got.receipts_root() })))

View File

@@ -11,7 +11,6 @@ ethkey = { path = "../../accounts/ethkey" }
heapsize = "0.4"
keccak-hash = "0.1"
parity-bytes = "0.1"
parity-machine = { path = "../../machine" }
rlp = { version = "0.3.0", features = ["ethereum"] }
rlp_derive = { path = "../../util/rlp-derive" }
unexpected = { path = "../../util/unexpected" }

View File

@@ -71,28 +71,3 @@ impl Decodable for PendingTransition {
}
}
/// Verifier for all blocks within an epoch with self-contained state.
pub trait EpochVerifier<M: ::parity_machine::Machine>: Send + Sync {
/// Lightly verify the next block header.
/// This may not be a header belonging to a different epoch.
fn verify_light(&self, header: &M::Header) -> Result<(), M::Error>;
/// Perform potentially heavier checks on the next block header.
fn verify_heavy(&self, header: &M::Header) -> Result<(), M::Error> {
self.verify_light(header)
}
/// Check a finality proof against this epoch verifier.
/// Returns `Some(hashes)` if the proof proves finality of these hashes.
/// Returns `None` if the proof doesn't prove anything.
fn check_finality_proof(&self, _proof: &[u8]) -> Option<Vec<H256>> {
None
}
}
/// Special "no-op" verifier for stateless, epoch-less engines.
pub struct NoOp;
impl<M: ::parity_machine::Machine> EpochVerifier<M> for NoOp {
fn verify_light(&self, _header: &M::Header) -> Result<(), M::Error> { Ok(()) }
}

View File

@@ -16,7 +16,6 @@
//! Block header.
use std::cmp;
use hash::{KECCAK_NULL_RLP, KECCAK_EMPTY_LIST_RLP, keccak};
use heapsize::HeapSizeOf;
use ethereum_types::{H256, U256, Address, Bloom};
@@ -342,7 +341,7 @@ impl Decodable for Header {
number: r.val_at(8)?,
gas_limit: r.val_at(9)?,
gas_used: r.val_at(10)?,
timestamp: cmp::min(r.val_at::<U256>(11)?, u64::max_value().into()).as_u64(),
timestamp: r.val_at(11)?,
extra_data: r.val_at(12)?,
seal: vec![],
hash: keccak(r.as_raw()).into(),
@@ -368,44 +367,11 @@ impl HeapSizeOf for Header {
}
}
impl ::parity_machine::Header for Header {
fn bare_hash(&self) -> H256 { Header::bare_hash(self) }
fn hash(&self) -> H256 { Header::hash(self) }
fn seal(&self) -> &[Vec<u8>] { Header::seal(self) }
fn author(&self) -> &Address { Header::author(self) }
fn number(&self) -> BlockNumber { Header::number(self) }
}
impl ::parity_machine::ScoredHeader for Header {
type Value = U256;
fn score(&self) -> &U256 { self.difficulty() }
fn set_score(&mut self, score: U256) { self.set_difficulty(score) }
}
impl ::parity_machine::Header for ExtendedHeader {
fn bare_hash(&self) -> H256 { self.header.bare_hash() }
fn hash(&self) -> H256 { self.header.hash() }
fn seal(&self) -> &[Vec<u8>] { self.header.seal() }
fn author(&self) -> &Address { self.header.author() }
fn number(&self) -> BlockNumber { self.header.number() }
}
impl ::parity_machine::ScoredHeader for ExtendedHeader {
type Value = U256;
fn score(&self) -> &U256 { self.header.difficulty() }
fn set_score(&mut self, score: U256) { self.header.set_difficulty(score) }
}
impl ::parity_machine::TotalScoredHeader for ExtendedHeader {
type Value = U256;
fn total_score(&self) -> U256 { self.parent_total_difficulty + *self.header.difficulty() }
}
impl ::parity_machine::FinalizableHeader for ExtendedHeader {
fn is_finalized(&self) -> bool { self.is_finalized }
impl ExtendedHeader {
/// Returns combined difficulty of all ancestors together with the difficulty of this header.
pub fn total_score(&self) -> U256 {
self.parent_total_difficulty + *self.header.difficulty()
}
}
#[cfg(test)]
@@ -445,4 +411,15 @@ mod tests {
assert_eq!(header_rlp, encoded_header);
}
#[test]
fn reject_header_with_large_timestamp() {
// that's rlp of block header created with ethash engine.
// The encoding contains a large timestamp (295147905179352825856)
let header_rlp = "f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d891000000000000000000080a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23".from_hex().unwrap();
// This should fail decoding timestamp
let header: Result<Header, _> = rlp::decode(&header_rlp);
assert_eq!(header.unwrap_err(), rlp::DecoderError::RlpIsTooBig);
}
}

View File

@@ -17,7 +17,7 @@
//! Unique identifiers.
use ethereum_types::H256;
use {BlockNumber};
use BlockNumber;
/// Uniquely identifies block.
#[derive(Debug, PartialEq, Copy, Clone, Hash, Eq)]

View File

@@ -39,7 +39,6 @@ extern crate ethkey;
extern crate heapsize;
extern crate keccak_hash as hash;
extern crate parity_bytes as bytes;
extern crate parity_machine;
extern crate rlp;
extern crate unexpected;

View File

@@ -18,7 +18,7 @@
use std::time::{Instant, Duration};
use ethereum_types::{H256, U256};
use ethcore::client::{self, EvmTestClient, EvmTestError, TransactResult};
use ethcore::client::{self, EvmTestClient, EvmTestError, TransactErr, TransactSuccess};
use ethcore::{state, state_db, trace, spec, pod_state, TrieSpec};
use ethjson;
use types::transaction;
@@ -130,7 +130,7 @@ pub fn run_transaction<T: Informant>(
let result = run(&spec, trie_spec, transaction.gas, pre_state, |mut client| {
let result = client.transact(env_info, transaction, trace::NoopTracer, informant);
match result {
TransactResult::Ok { state_root, gas_left, output, vm_trace, end_state, .. } => {
Ok(TransactSuccess { state_root, gas_left, output, vm_trace, end_state, .. }) => {
if state_root != post_root {
(Err(EvmTestError::PostCondition(format!(
"State root mismatch (got: {:#x}, expected: {:#x})",
@@ -141,7 +141,7 @@ pub fn run_transaction<T: Informant>(
(Ok(output), state_root, end_state, Some(gas_left), vm_trace)
}
},
TransactResult::Err { state_root, error, end_state } => {
Err(TransactErr { state_root, error, end_state }) => {
(Err(EvmTestError::PostCondition(format!(
"Unexpected execution error: {:?}", error
))), state_root, end_state, None, None)

57
json/src/spec/clique.rs Normal file
View File

@@ -0,0 +1,57 @@
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.
// Parity Ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
//! Clique params deserialization.
use std::num::NonZeroU64;
/// Clique params deserialization.
#[derive(Debug, PartialEq, Deserialize)]
pub struct CliqueParams {
/// period as defined in EIP
pub period: Option<u64>,
/// epoch length as defined in EIP
pub epoch: Option<NonZeroU64>
}
/// Clique engine deserialization.
#[derive(Debug, PartialEq, Deserialize)]
pub struct Clique {
/// CliqueEngine params
pub params: CliqueParams,
}
#[cfg(test)]
mod tests {
use serde_json;
use uint::Uint;
use ethereum_types::U256;
use super::*;
#[test]
fn clique_deserialization() {
let s = r#"{
"params": {
"period": 5,
"epoch": 30000
}
}"#;
let deserialized: Clique = serde_json::from_str(s).unwrap();
assert_eq!(deserialized.params.period, Some(5u64));
assert_eq!(deserialized.params.epoch, NonZeroU64::new(30000));
}
}

View File

@@ -16,7 +16,7 @@
//! Engine deserialization.
use super::{Ethash, BasicAuthority, AuthorityRound, NullEngine, InstantSeal};
use super::{Ethash, BasicAuthority, AuthorityRound, NullEngine, InstantSeal, Clique};
/// Engine deserialization.
#[derive(Debug, PartialEq, Deserialize)]
@@ -34,6 +34,8 @@ pub enum Engine {
BasicAuthority(BasicAuthority),
/// AuthorityRound engine.
AuthorityRound(AuthorityRound),
/// Clique engine.
Clique(Clique)
}
#[cfg(test)]
@@ -130,5 +132,19 @@ mod tests {
Engine::AuthorityRound(_) => {}, // AuthorityRound is unit tested in its own file.
_ => panic!(),
};
let s = r#"{
"clique": {
"params": {
"period": 15,
"epoch": 30000
}
}
}"#;
let deserialized: Engine = serde_json::from_str(s).unwrap();
match deserialized {
Engine::Clique(_) => {}, // Clique is unit tested in its own file.
_ => panic!(),
};
}
}

View File

@@ -31,6 +31,7 @@ pub mod authority_round;
pub mod null_engine;
pub mod instant_seal;
pub mod hardcoded_sync;
pub mod clique;
pub use self::account::Account;
pub use self::builtin::{Builtin, Pricing, Linear};
@@ -44,6 +45,7 @@ pub use self::ethash::{Ethash, EthashParams, BlockReward};
pub use self::validator_set::ValidatorSet;
pub use self::basic_authority::{BasicAuthority, BasicAuthorityParams};
pub use self::authority_round::{AuthorityRound, AuthorityRoundParams};
pub use self::clique::{Clique, CliqueParams};
pub use self::null_engine::{NullEngine, NullEngineParams};
pub use self::instant_seal::{InstantSeal, InstantSealParams};
pub use self::hardcoded_sync::HardcodedSync;

View File

@@ -1,8 +0,0 @@
[package]
name = "parity-machine"
version = "0.1.0"
description = "Generalization of a state machine for consensus engines"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
ethereum-types = "0.4"

View File

@@ -1,132 +0,0 @@
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.
// Parity Ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
//! Generalization of a state machine for a consensus engine.
//! This will define traits for the header, block, and state of a blockchain.
extern crate ethereum_types;
use ethereum_types::{H256, U256, Address};
/// A header. This contains important metadata about the block, as well as a
/// "seal" that indicates validity to a consensus engine.
pub trait Header {
/// Cryptographic hash of the header, excluding the seal.
fn bare_hash(&self) -> H256;
/// Cryptographic hash of the header, including the seal.
fn hash(&self) -> H256;
/// Get a reference to the seal fields.
fn seal(&self) -> &[Vec<u8>];
/// The author of the header.
fn author(&self) -> &Address;
/// The number of the header.
fn number(&self) -> u64;
}
/// A header with an associated score (difficulty in PoW terms)
pub trait ScoredHeader: Header {
type Value;
/// Get the score of this header.
fn score(&self) -> &Self::Value;
/// Set the score of this header.
fn set_score(&mut self, score: Self::Value);
}
/// A header with associated total score.
pub trait TotalScoredHeader: Header {
type Value;
/// Get the total score of this header.
fn total_score(&self) -> Self::Value;
}
/// A header with finalized information.
pub trait FinalizableHeader: Header {
/// Get whether this header is considered finalized, so that it will never be replaced in reorganization.
fn is_finalized(&self) -> bool;
}
/// A header with metadata information.
pub trait WithMetadataHeader: Header {
/// Get the current header metadata.
fn metadata(&self) -> Option<&[u8]>;
}
/// A "live" block is one which is in the process of the transition.
/// The state of this block can be mutated by arbitrary rules of the
/// state transition function.
pub trait LiveBlock: 'static {
/// The block header type;
type Header: Header;
/// Get a reference to the header.
fn header(&self) -> &Self::Header;
/// Get a reference to the uncle headers. If the block type doesn't
/// support uncles, return the empty slice.
fn uncles(&self) -> &[Self::Header];
}
/// Trait for blocks which have a transaction type.
pub trait Transactions: LiveBlock {
/// The transaction type.
type Transaction;
/// Get a reference to the transactions in this block.
fn transactions(&self) -> &[Self::Transaction];
}
/// Generalization of types surrounding blockchain-suitable state machines.
pub trait Machine: for<'a> LocalizedMachine<'a> {
/// The block header type.
type Header: Header;
/// The live block type.
type LiveBlock: LiveBlock<Header=Self::Header>;
/// Block header with metadata information.
type ExtendedHeader: Header;
/// A handle to a blockchain client for this machine.
type EngineClient: ?Sized;
/// A description of needed auxiliary data.
type AuxiliaryRequest;
/// Actions taken on ancestry blocks when commiting a new block.
type AncestryAction;
/// Errors which can occur when querying or interacting with the machine.
type Error;
/// Get the balance, in base units, associated with an account.
/// Extracts data from the live block.
fn balance(&self, live: &Self::LiveBlock, address: &Address) -> Result<U256, Self::Error>;
/// Increment the balance of an account in the state of the live block.
fn add_balance(&self, live: &mut Self::LiveBlock, address: &Address, amount: &U256) -> Result<(), Self::Error>;
}
/// Machine-related types localized to a specific lifetime.
// TODO: this is a workaround for a lack of associated type constructors in the language.
pub trait LocalizedMachine<'a>: Sync + Send {
/// Definition of auxiliary data associated to a specific block.
type AuxiliaryData: 'a;
/// A context providing access to the state in a controlled capacity.
/// Generally also provides verifiable proofs.
type StateContext: ?Sized + 'a;
}

View File

@@ -32,7 +32,7 @@ parking_lot = "0.7"
price-info = { path = "./price-info", optional = true }
rlp = { version = "0.3.0", features = ["ethereum"] }
trace-time = "0.1"
transaction-pool = "1.13"
transaction-pool = "2.0"
[dev-dependencies]
env_logger = "0.5"

View File

@@ -92,7 +92,7 @@ impl txpool::Listener<Transaction> for Logger {
}
}
fn rejected(&mut self, _tx: &Arc<Transaction>, reason: &txpool::ErrorKind) {
fn rejected<H: fmt::Debug + fmt::LowerHex>(&mut self, _tx: &Arc<Transaction>, reason: &txpool::Error<H>) {
trace!(target: "txqueue", "Rejected {}.", reason);
}

View File

@@ -171,7 +171,7 @@ impl txpool::Listener<Transaction> for LocalTransactionsList {
}
}
fn rejected(&mut self, tx: &Arc<Transaction>, reason: &txpool::ErrorKind) {
fn rejected<H: fmt::Debug + fmt::LowerHex>(&mut self, tx: &Arc<Transaction>, reason: &txpool::Error<H>) {
if !tx.priority().is_local() {
return;
}

View File

@@ -27,6 +27,7 @@ mod ready;
pub mod client;
pub mod local_transactions;
pub mod replace;
pub mod scoring;
pub mod verifier;
@@ -121,7 +122,7 @@ pub trait ScoredTransaction {
}
/// Verified transaction stored in the pool.
#[derive(Debug, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct VerifiedTransaction {
transaction: transaction::PendingTransaction,
// TODO [ToDr] hash and sender should go directly from the transaction

View File

@@ -27,7 +27,7 @@ use txpool::{self, Verifier};
use types::transaction;
use pool::{
self, scoring, verifier, client, ready, listener,
self, replace, scoring, verifier, client, ready, listener,
PrioritizationStrategy, PendingOrdering, PendingSettings,
};
use pool::local_transactions::LocalTransactionsList;
@@ -240,7 +240,7 @@ impl TransactionQueue {
///
/// Given blockchain and state access (Client)
/// verifies and imports transactions to the pool.
pub fn import<C: client::Client>(
pub fn import<C: client::Client + client::NonceClient + Clone>(
&self,
client: C,
transactions: Vec<verifier::Transaction>,
@@ -263,12 +263,14 @@ impl TransactionQueue {
};
let verifier = verifier::Verifier::new(
client,
client.clone(),
options,
self.insertion_id.clone(),
transaction_to_replace,
);
let mut replace = replace::ReplaceByScoreAndReadiness::new(self.pool.read().scoring().clone(), client);
let results = transactions
.into_iter()
.map(|transaction| {
@@ -286,7 +288,7 @@ impl TransactionQueue {
let imported = verifier
.verify_transaction(transaction)
.and_then(|verified| {
self.pool.write().import(verified).map_err(convert_error)
self.pool.write().import(verified, &mut replace).map_err(convert_error)
});
match imported {
@@ -579,17 +581,13 @@ impl TransactionQueue {
}
}
fn convert_error(err: txpool::Error) -> transaction::Error {
use self::txpool::ErrorKind;
fn convert_error<H: fmt::Debug + fmt::LowerHex>(err: txpool::Error<H>) -> transaction::Error {
use self::txpool::Error;
match *err.kind() {
ErrorKind::AlreadyImported(..) => transaction::Error::AlreadyImported,
ErrorKind::TooCheapToEnter(..) => transaction::Error::LimitReached,
ErrorKind::TooCheapToReplace(..) => transaction::Error::TooCheapToReplace,
ref e => {
warn!(target: "txqueue", "Unknown import error: {:?}", e);
transaction::Error::NotAllowed
},
match err {
Error::AlreadyImported(..) => transaction::Error::AlreadyImported,
Error::TooCheapToEnter(..) => transaction::Error::LimitReached,
Error::TooCheapToReplace(..) => transaction::Error::TooCheapToReplace
}
}

415
miner/src/pool/replace.rs Normal file
View File

@@ -0,0 +1,415 @@
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.
// Parity Ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
//! Replacing Transactions
//!
//! When queue limits are reached, a new transaction may replace one already
//! in the pool. The decision whether to reject, replace or retain both is
//! delegated to an implementation of `ShouldReplace`.
//!
//! Here we decide based on the sender, the nonce and gas price, and finally
//! on the `Readiness` of the transactions when comparing them
use std::cmp;
use ethereum_types::{U256, H160 as Address};
use txpool::{self, scoring::{Choice, Scoring}, ReplaceTransaction};
use txpool::VerifiedTransaction;
use super::{client, ScoredTransaction};
/// Choose whether to replace based on the sender, the score and finally the
/// `Readiness` of the transactions being compared.
#[derive(Debug)]
pub struct ReplaceByScoreAndReadiness<S, C> {
scoring: S,
client: C,
}
impl<S, C> ReplaceByScoreAndReadiness<S, C> {
/// Create a new `ReplaceByScoreAndReadiness`
pub fn new(scoring: S, client: C) -> Self {
ReplaceByScoreAndReadiness { scoring, client }
}
}
impl<T, S, C> txpool::ShouldReplace<T> for ReplaceByScoreAndReadiness<S, C>
where
T: VerifiedTransaction<Sender = Address> + ScoredTransaction + PartialEq,
S: Scoring<T>,
C: client::NonceClient,
{
fn should_replace(
&self,
old: &ReplaceTransaction<T>,
new: &ReplaceTransaction<T>,
) -> Choice {
let both_local = old.priority().is_local() && new.priority().is_local();
if old.sender() == new.sender() {
// prefer earliest transaction
match new.nonce().cmp(&old.nonce()) {
cmp::Ordering::Equal => self.scoring.choose(&old, &new),
_ if both_local => Choice::InsertNew,
cmp::Ordering::Less => Choice::ReplaceOld,
cmp::Ordering::Greater => Choice::RejectNew,
}
} else if both_local {
Choice::InsertNew
} else {
let old_score = (old.priority(), old.gas_price());
let new_score = (new.priority(), new.gas_price());
if new_score > old_score {
let state = &self.client;
// calculate readiness based on state nonce + pooled txs from same sender
let is_ready = |replace: &ReplaceTransaction<T>| {
let mut nonce = state.account_nonce(replace.sender());
if let Some(txs) = replace.pooled_by_sender {
for tx in txs.iter() {
if nonce == tx.nonce() && *tx.transaction != ***replace.transaction {
nonce = nonce.saturating_add(U256::from(1))
} else {
break
}
}
}
nonce == replace.nonce()
};
if !is_ready(new) && is_ready(old) {
// prevent a ready transaction being replace by a non-ready transaction
Choice::RejectNew
} else {
Choice::ReplaceOld
}
} else {
Choice::RejectNew
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::Arc;
use ethkey::{Random, Generator, KeyPair};
use pool::tests::tx::{Tx, TxExt};
use pool::tests::client::TestClient;
use pool::scoring::*;
use pool::{PrioritizationStrategy, VerifiedTransaction};
use txpool::scoring::Choice::*;
use txpool::ShouldReplace;
fn local_tx_verified(tx: Tx, keypair: &KeyPair) -> VerifiedTransaction {
let mut verified_tx = tx.unsigned().sign(keypair.secret(), None).verified();
verified_tx.priority = ::pool::Priority::Local;
verified_tx
}
fn should_replace(replace: &ShouldReplace<VerifiedTransaction>, old: VerifiedTransaction, new: VerifiedTransaction) -> Choice {
let old_tx = txpool::Transaction { insertion_id: 0, transaction: Arc::new(old) };
let new_tx = txpool::Transaction { insertion_id: 0, transaction: Arc::new(new) };
let old = ReplaceTransaction::new(&old_tx, Default::default());
let new = ReplaceTransaction::new(&new_tx, Default::default());
replace.should_replace(&old, &new)
}
#[test]
fn should_always_accept_local_transactions_unless_same_sender_and_nonce() {
let scoring = NonceAndGasPrice(PrioritizationStrategy::GasPriceOnly);
let client = TestClient::new().with_nonce(1);
let replace = ReplaceByScoreAndReadiness::new(scoring, client);
// same sender txs
let keypair = Random.generate().unwrap();
let same_sender_tx1 = local_tx_verified(Tx {
nonce: 1,
gas_price: 1,
..Default::default()
}, &keypair);
let same_sender_tx2 = local_tx_verified(Tx {
nonce: 2,
gas_price: 100,
..Default::default()
}, &keypair);
let same_sender_tx3 = local_tx_verified(Tx {
nonce: 2,
gas_price: 200,
..Default::default()
}, &keypair);
// different sender txs
let sender1 = Random.generate().unwrap();
let different_sender_tx1 = local_tx_verified(Tx {
nonce: 2,
gas_price: 1,
..Default::default()
}, &sender1);
let sender2 = Random.generate().unwrap();
let different_sender_tx2 = local_tx_verified(Tx {
nonce: 1,
gas_price: 10,
..Default::default()
}, &sender2);
assert_eq!(should_replace(&replace, same_sender_tx1.clone(), same_sender_tx2.clone()), InsertNew);
assert_eq!(should_replace(&replace, same_sender_tx2.clone(), same_sender_tx1.clone()), InsertNew);
assert_eq!(should_replace(&replace, different_sender_tx1.clone(), different_sender_tx2.clone()), InsertNew);
assert_eq!(should_replace(&replace, different_sender_tx2.clone(), different_sender_tx1.clone()), InsertNew);
// txs with same sender and nonce
assert_eq!(should_replace(&replace, same_sender_tx2.clone(), same_sender_tx3.clone()), ReplaceOld);
assert_eq!(should_replace(&replace, same_sender_tx3.clone(), same_sender_tx2.clone()), RejectNew);
}
#[test]
fn should_replace_same_sender_by_nonce() {
let scoring = NonceAndGasPrice(PrioritizationStrategy::GasPriceOnly);
let client = TestClient::new().with_nonce(1);
let replace = ReplaceByScoreAndReadiness::new(scoring, client);
let tx1 = Tx {
nonce: 1,
gas_price: 1,
..Default::default()
};
let tx2 = Tx {
nonce: 2,
gas_price: 100,
..Default::default()
};
let tx3 = Tx {
nonce: 2,
gas_price: 110,
..Default::default()
};
let tx4 = Tx {
nonce: 2,
gas_price: 130,
..Default::default()
};
let keypair = Random.generate().unwrap();
let txs = vec![tx1, tx2, tx3, tx4].into_iter().map(|tx| {
tx.unsigned().sign(keypair.secret(), None).verified()
}).collect::<Vec<_>>();
assert_eq!(should_replace(&replace, txs[0].clone(), txs[1].clone()), RejectNew);
assert_eq!(should_replace(&replace, txs[1].clone(), txs[0].clone()), ReplaceOld);
assert_eq!(should_replace(&replace, txs[1].clone(), txs[2].clone()), RejectNew);
assert_eq!(should_replace(&replace, txs[2].clone(), txs[1].clone()), RejectNew);
assert_eq!(should_replace(&replace, txs[1].clone(), txs[3].clone()), ReplaceOld);
assert_eq!(should_replace(&replace, txs[3].clone(), txs[1].clone()), RejectNew);
}
#[test]
fn should_replace_different_sender_by_priority_and_gas_price() {
// given
let scoring = NonceAndGasPrice(PrioritizationStrategy::GasPriceOnly);
let client = TestClient::new().with_nonce(0);
let replace = ReplaceByScoreAndReadiness::new(scoring, client);
let tx_regular_low_gas = {
let tx = Tx {
nonce: 1,
gas_price: 1,
..Default::default()
};
tx.signed().verified()
};
let tx_regular_high_gas = {
let tx = Tx {
nonce: 2,
gas_price: 10,
..Default::default()
};
tx.signed().verified()
};
let tx_local_low_gas = {
let tx = Tx {
nonce: 2,
gas_price: 1,
..Default::default()
};
let mut verified_tx = tx.signed().verified();
verified_tx.priority = ::pool::Priority::Local;
verified_tx
};
let tx_local_high_gas = {
let tx = Tx {
nonce: 1,
gas_price: 10,
..Default::default()
};
let mut verified_tx = tx.signed().verified();
verified_tx.priority = ::pool::Priority::Local;
verified_tx
};
assert_eq!(should_replace(&replace, tx_regular_low_gas.clone(), tx_regular_high_gas.clone()), ReplaceOld);
assert_eq!(should_replace(&replace, tx_regular_high_gas.clone(), tx_regular_low_gas.clone()), RejectNew);
assert_eq!(should_replace(&replace, tx_regular_high_gas.clone(), tx_local_low_gas.clone()), ReplaceOld);
assert_eq!(should_replace(&replace, tx_local_low_gas.clone(), tx_regular_high_gas.clone()), RejectNew);
assert_eq!(should_replace(&replace, tx_local_low_gas.clone(), tx_local_high_gas.clone()), InsertNew);
assert_eq!(should_replace(&replace, tx_local_high_gas.clone(), tx_regular_low_gas.clone()), RejectNew);
}
#[test]
fn should_not_replace_ready_transaction_with_future_transaction() {
let scoring = NonceAndGasPrice(PrioritizationStrategy::GasPriceOnly);
let client = TestClient::new().with_nonce(1);
let replace = ReplaceByScoreAndReadiness::new(scoring, client);
let tx_ready_low_score = {
let tx = Tx {
nonce: 1,
gas_price: 1,
..Default::default()
};
tx.signed().verified()
};
let tx_future_high_score = {
let tx = Tx {
nonce: 3, // future nonce
gas_price: 10,
..Default::default()
};
tx.signed().verified()
};
assert_eq!(should_replace(&replace, tx_ready_low_score, tx_future_high_score), RejectNew);
}
#[test]
fn should_compute_readiness_with_pooled_transactions_from_the_same_sender_as_the_existing_transaction() {
let scoring = NonceAndGasPrice(PrioritizationStrategy::GasPriceOnly);
let client = TestClient::new().with_nonce(1);
let replace = ReplaceByScoreAndReadiness::new(scoring, client);
let old_sender = Random.generate().unwrap();
let tx_old_ready_1 = {
let tx = Tx {
nonce: 1,
gas_price: 1,
..Default::default()
};
tx.unsigned().sign(&old_sender.secret(), None).verified()
};
let tx_old_ready_2 = {
let tx = Tx {
nonce: 2,
gas_price: 1,
..Default::default()
};
tx.unsigned().sign(&old_sender.secret(), None).verified()
};
let tx_old_ready_3 = {
let tx = Tx {
nonce: 3,
gas_price: 1,
..Default::default()
};
tx.unsigned().sign(&old_sender.secret(), None).verified()
};
let new_tx = {
let tx = Tx {
nonce: 3, // future nonce
gas_price: 10,
..Default::default()
};
tx.signed().verified()
};
let old_tx = txpool::Transaction { insertion_id: 0, transaction: Arc::new(tx_old_ready_3) };
let pooled_txs = [
txpool::Transaction { insertion_id: 0, transaction: Arc::new(tx_old_ready_1) },
txpool::Transaction { insertion_id: 0, transaction: Arc::new(tx_old_ready_2) },
];
let new_tx = txpool::Transaction { insertion_id: 0, transaction: Arc::new(new_tx) };
let old = ReplaceTransaction::new(&old_tx, Some(&pooled_txs));
let new = ReplaceTransaction::new(&new_tx, Default::default());
assert_eq!(replace.should_replace(&old, &new), RejectNew);
}
#[test]
fn should_compute_readiness_with_pooled_transactions_from_the_same_sender_as_the_new_transaction() {
let scoring = NonceAndGasPrice(PrioritizationStrategy::GasPriceOnly);
let client = TestClient::new().with_nonce(1);
let replace = ReplaceByScoreAndReadiness::new(scoring, client);
// current transaction is ready but has a lower gas price than the new one
let old_tx = {
let tx = Tx {
nonce: 1,
gas_price: 1,
..Default::default()
};
tx.signed().verified()
};
let new_sender = Random.generate().unwrap();
let tx_new_ready_1 = {
let tx = Tx {
nonce: 1,
gas_price: 1,
..Default::default()
};
tx.unsigned().sign(&new_sender.secret(), None).verified()
};
let tx_new_ready_2 = {
let tx = Tx {
nonce: 2,
gas_price: 1,
..Default::default()
};
tx.unsigned().sign(&new_sender.secret(), None).verified()
};
let tx_new_ready_3 = {
let tx = Tx {
nonce: 3,
gas_price: 10, // hi
..Default::default()
};
tx.unsigned().sign(&new_sender.secret(), None).verified()
};
let old_tx = txpool::Transaction { insertion_id: 0, transaction: Arc::new(old_tx) };
let new_tx = txpool::Transaction { insertion_id: 0, transaction: Arc::new(tx_new_ready_3) };
let pooled_txs = [
txpool::Transaction { insertion_id: 0, transaction: Arc::new(tx_new_ready_1) },
txpool::Transaction { insertion_id: 0, transaction: Arc::new(tx_new_ready_2) },
];
let old = ReplaceTransaction::new(&old_tx, None);
let new = ReplaceTransaction::new(&new_tx, Some(&pooled_txs));
assert_eq!(replace.should_replace(&old, &new), ReplaceOld);
}
}

View File

@@ -122,29 +122,6 @@ impl<P> txpool::Scoring<P> for NonceAndGasPrice where P: ScoredTransaction + txp
}
}
fn should_replace(&self, old: &P, new: &P) -> scoring::Choice {
let both_local = old.priority().is_local() && new.priority().is_local();
if old.sender() == new.sender() {
// prefer earliest transaction
match new.nonce().cmp(&old.nonce()) {
cmp::Ordering::Equal => self.choose(old, new),
_ if both_local => scoring::Choice::InsertNew,
cmp::Ordering::Less => scoring::Choice::ReplaceOld,
cmp::Ordering::Greater => scoring::Choice::RejectNew,
}
} else if both_local {
scoring::Choice::InsertNew
} else {
let old_score = (old.priority(), old.gas_price());
let new_score = (new.priority(), new.gas_price());
if new_score > old_score {
scoring::Choice::ReplaceOld
} else {
scoring::Choice::RejectNew
}
}
}
fn should_ignore_sender_limit(&self, new: &P) -> bool {
new.priority().is_local()
}
@@ -155,156 +132,8 @@ mod tests {
use super::*;
use std::sync::Arc;
use ethkey::{Random, Generator, KeyPair};
use pool::tests::tx::{Tx, TxExt};
use txpool::Scoring;
use txpool::scoring::Choice::*;
fn local_tx_verified(tx: Tx, keypair: &KeyPair) -> VerifiedTransaction {
let mut verified_tx = tx.unsigned().sign(keypair.secret(), None).verified();
verified_tx.priority = ::pool::Priority::Local;
verified_tx
}
#[test]
fn should_always_accept_local_transactions_unless_same_sender_and_nonce() {
let scoring = NonceAndGasPrice(PrioritizationStrategy::GasPriceOnly);
// same sender txs
let keypair = Random.generate().unwrap();
let same_sender_tx1 = local_tx_verified(Tx {
nonce: 1,
gas_price: 1,
..Default::default()
}, &keypair);
let same_sender_tx2 = local_tx_verified(Tx {
nonce: 2,
gas_price: 100,
..Default::default()
}, &keypair);
let same_sender_tx3 = local_tx_verified(Tx {
nonce: 2,
gas_price: 200,
..Default::default()
}, &keypair);
// different sender txs
let different_sender_tx1 = local_tx_verified(Tx {
nonce: 2,
gas_price: 1,
..Default::default()
}, &Random.generate().unwrap());
let different_sender_tx2 = local_tx_verified(Tx {
nonce: 1,
gas_price: 10,
..Default::default()
}, &Random.generate().unwrap());
assert_eq!(scoring.should_replace(&same_sender_tx1, &same_sender_tx2), InsertNew);
assert_eq!(scoring.should_replace(&same_sender_tx2, &same_sender_tx1), InsertNew);
assert_eq!(scoring.should_replace(&different_sender_tx1, &different_sender_tx2), InsertNew);
assert_eq!(scoring.should_replace(&different_sender_tx2, &different_sender_tx1), InsertNew);
// txs with same sender and nonce
assert_eq!(scoring.should_replace(&same_sender_tx2, &same_sender_tx3), ReplaceOld);
assert_eq!(scoring.should_replace(&same_sender_tx3, &same_sender_tx2), RejectNew);
}
#[test]
fn should_replace_same_sender_by_nonce() {
let scoring = NonceAndGasPrice(PrioritizationStrategy::GasPriceOnly);
let tx1 = Tx {
nonce: 1,
gas_price: 1,
..Default::default()
};
let tx2 = Tx {
nonce: 2,
gas_price: 100,
..Default::default()
};
let tx3 = Tx {
nonce: 2,
gas_price: 110,
..Default::default()
};
let tx4 = Tx {
nonce: 2,
gas_price: 130,
..Default::default()
};
let keypair = Random.generate().unwrap();
let txs = vec![tx1, tx2, tx3, tx4].into_iter().map(|tx| {
tx.unsigned().sign(keypair.secret(), None).verified()
}).collect::<Vec<_>>();
assert_eq!(scoring.should_replace(&txs[0], &txs[1]), RejectNew);
assert_eq!(scoring.should_replace(&txs[1], &txs[0]), ReplaceOld);
assert_eq!(scoring.should_replace(&txs[1], &txs[2]), RejectNew);
assert_eq!(scoring.should_replace(&txs[2], &txs[1]), RejectNew);
assert_eq!(scoring.should_replace(&txs[1], &txs[3]), ReplaceOld);
assert_eq!(scoring.should_replace(&txs[3], &txs[1]), RejectNew);
}
#[test]
fn should_replace_different_sender_by_priority_and_gas_price() {
// given
let scoring = NonceAndGasPrice(PrioritizationStrategy::GasPriceOnly);
let tx_regular_low_gas = {
let tx = Tx {
nonce: 1,
gas_price: 1,
..Default::default()
};
tx.signed().verified()
};
let tx_regular_high_gas = {
let tx = Tx {
nonce: 2,
gas_price: 10,
..Default::default()
};
tx.signed().verified()
};
let tx_local_low_gas = {
let tx = Tx {
nonce: 2,
gas_price: 1,
..Default::default()
};
let mut verified_tx = tx.signed().verified();
verified_tx.priority = ::pool::Priority::Local;
verified_tx
};
let tx_local_high_gas = {
let tx = Tx {
nonce: 1,
gas_price: 10,
..Default::default()
};
let mut verified_tx = tx.signed().verified();
verified_tx.priority = ::pool::Priority::Local;
verified_tx
};
assert_eq!(scoring.should_replace(&tx_regular_low_gas, &tx_regular_high_gas), ReplaceOld);
assert_eq!(scoring.should_replace(&tx_regular_high_gas, &tx_regular_low_gas), RejectNew);
assert_eq!(scoring.should_replace(&tx_regular_high_gas, &tx_local_low_gas), ReplaceOld);
assert_eq!(scoring.should_replace(&tx_local_low_gas, &tx_regular_high_gas), RejectNew);
assert_eq!(scoring.should_replace(&tx_local_low_gas, &tx_local_high_gas), InsertNew);
assert_eq!(scoring.should_replace(&tx_local_high_gas, &tx_regular_low_gas), RejectNew);
}
#[test]
fn should_calculate_score_correctly() {

View File

@@ -16,11 +16,15 @@
//! A service transactions contract checker.
use call_contract::{CallContract, RegistryInfo};
use std::collections::HashMap;
use std::mem;
use std::sync::Arc;
use call_contract::{RegistryInfo, CallContract};
use types::ids::BlockId;
use types::transaction::SignedTransaction;
use ethabi::FunctionOutputDecoder;
use ethereum_types::Address;
use parking_lot::RwLock;
use_contract!(service_transaction, "res/contracts/service_transaction.json");
@@ -28,9 +32,12 @@ const SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME: &'static str = "service_transa
/// Service transactions checker.
#[derive(Default, Clone)]
pub struct ServiceTransactionChecker;
pub struct ServiceTransactionChecker {
certified_addresses_cache: Arc<RwLock<HashMap<Address, bool>>>
}
impl ServiceTransactionChecker {
/// Checks if given address in tx is whitelisted to send service transactions.
pub fn check<C: CallContract + RegistryInfo>(&self, client: &C, tx: &SignedTransaction) -> Result<bool, String> {
let sender = tx.sender();
@@ -44,9 +51,42 @@ impl ServiceTransactionChecker {
/// Checks if given address is whitelisted to send service transactions.
pub fn check_address<C: CallContract + RegistryInfo>(&self, client: &C, sender: Address) -> Result<bool, String> {
trace!(target: "txqueue", "Checking service transaction checker contract from {}", sender);
if let Some(allowed) = self.certified_addresses_cache.try_read().as_ref().and_then(|c| c.get(&sender)) {
return Ok(*allowed);
}
let contract_address = client.registry_address(SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME.to_owned(), BlockId::Latest)
.ok_or_else(|| "contract is not configured")?;
trace!(target: "txqueue", "Checking service transaction checker contract from {}", sender);
self.call_contract(client, contract_address, sender).and_then(|allowed| {
if let Some(mut cache) = self.certified_addresses_cache.try_write() {
cache.insert(sender, allowed);
};
Ok(allowed)
})
}
/// Refresh certified addresses cache
pub fn refresh_cache<C: CallContract + RegistryInfo>(&self, client: &C) -> Result<bool, String> {
trace!(target: "txqueue", "Refreshing certified addresses cache");
// replace the cache with an empty list,
// since it's not recent it won't be used anyway.
let cache = mem::replace(&mut *self.certified_addresses_cache.write(), HashMap::default());
if let Some(contract_address) = client.registry_address(SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME.to_owned(), BlockId::Latest) {
let addresses: Vec<_> = cache.keys().collect();
let mut cache: HashMap<Address, bool> = HashMap::default();
for address in addresses {
let allowed = self.call_contract(client, contract_address, *address)?;
cache.insert(*address, allowed);
}
mem::replace(&mut *self.certified_addresses_cache.write(), cache);
Ok(true)
} else {
Ok(false)
}
}
fn call_contract<C: CallContract + RegistryInfo>(&self, client: &C, contract_address: Address, sender: Address) -> Result<bool, String> {
let (data, decoder) = service_transaction::functions::certified::call(sender);
let value = client.call_contract(BlockId::Latest, contract_address, data)?;
decoder.decode(&value).map_err(|e| e.to_string())

View File

@@ -11,7 +11,7 @@ crate-type = ["cdylib", "staticlib"]
[dependencies]
futures = "0.1.6"
jni = { version = "0.10.1", optional = true }
jni = { version = "0.11", optional = true }
panic_hook = { path = "../util/panic-hook" }
parity-ethereum = { path = "../", default-features = false }
tokio = "0.1.11"

View File

@@ -36,9 +36,6 @@ struct JavaCallback<'a> {
method_descriptor: &'a str,
}
unsafe impl<'a> Send for JavaCallback<'a> {}
unsafe impl<'a> Sync for JavaCallback<'a> {}
impl<'a> JavaCallback<'a> {
fn new(jvm: JavaVM, callback: GlobalRef) -> Self {
Self {

View File

@@ -300,7 +300,7 @@ usage! {
ARG arg_chain: (String) = "foundation", or |c: &Config| c.parity.as_ref()?.chain.clone(),
"--chain=[CHAIN]",
"Specify the blockchain type. CHAIN may be either a JSON chain specification file or ethereum, classic, poacore, tobalaba, expanse, musicoin, ellaism, easthub, social, mix, callisto, morden, ropsten, kovan, poasokol, testnet, or dev.",
"Specify the blockchain type. CHAIN may be either a JSON chain specification file or ethereum, classic, poacore, tobalaba, expanse, musicoin, ellaism, mix, callisto, morden, ropsten, kovan, rinkeby, goerli, kotti, poasokol, testnet, or dev.",
ARG arg_keys_path: (String) = "$BASE/keys", or |c: &Config| c.parity.as_ref()?.keys_path.clone(),
"--keys-path=[PATH]",
@@ -926,7 +926,7 @@ usage! {
"--whisper",
"Enable the Whisper network.",
ARG arg_whisper_pool_size: (usize) = 10usize, or |c: &Config| c.whisper.as_ref()?.pool_size.clone(),
ARG arg_whisper_pool_size: (usize) = 10usize, or |c: &Config| c.whisper.as_ref()?.pool_size.clone(),
"--whisper-pool-size=[MB]",
"Target size of the whisper message pool in megabytes.",

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