Compare commits

..

116 Commits

Author SHA1 Message Date
Afri Schoedon
78ceec6c6e Backports for beta 2.2.2 (#9976)
* version: bump beta to 2.2.2

* Add experimental RPCs flag (#9928)

* WiP

* Enable experimental RPCs.

* Keep existing blocks when restoring a Snapshot (#8643)

* Rename db_restore => client

* First step: make it compile!

* Second step: working implementation!

* Refactoring

* Fix tests

* PR Grumbles

* PR Grumbles WIP

* Migrate ancient blocks interating backward

* Early return in block migration if snapshot is aborted

* Remove RwLock getter (PR Grumble I)

* Remove dependency on `Client`: only used Traits

* Add test for recovering aborted snapshot recovery

* Add test for migrating old blocks

* Fix build

* PR Grumble I

* PR Grumble II

* PR Grumble III

* PR Grumble IV

* PR Grumble V

* PR Grumble VI

* Fix one test

* Fix test

* PR Grumble

* PR Grumbles

* PR Grumbles II

* Fix tests

* Release RwLock earlier

* Revert Cargo.lock

* Update _update ancient block_ logic: set local in `commit`

* Update typo in ethcore/src/snapshot/service.rs

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

* Adjust requests costs for light client (#9925)

* PIP Table Cost relative to average peers instead of max peers

* Add tracing in PIP new_cost_table

* Update stat peer_count

* Use number of leeching peers for Light serve costs

* Fix test::light_params_load_share_depends_on_max_peers (wrong type)

* Remove (now) useless test

* Remove `load_share` from LightParams.Config
Prevent div. by 0

* Add LEECHER_COUNT_FACTOR

* PR Grumble: u64 to u32 for f64 casting

* Prevent u32 overflow for avg_peer_count

* Add tests for LightSync::Statistics

* Fix empty steps (#9939)

* Don't send empty step twice or empty step then block.

* Perform basic validation of locally sealed blocks.

* Don't include empty step twice.

* prevent silent errors in daemon mode, closes #9367 (#9946)

* Fix a deadlock (#9952)

* Update informant:
  - decimal in Mgas/s
  - print every 5s (not randomly between 5s and 10s)

* Fix dead-lock in `blockchain.rs`

* Update locks ordering

* Fix light client informant while syncing (#9932)

* Add `is_idle` to LightSync to check importing status

* Use SyncStateWrapper to make sure is_idle gets updates

* Update is_major_import to use verified queue size as well

* Add comment for `is_idle`

* Add Debug to `SyncStateWrapper`

* `fn get` -> `fn into_inner`

*  ci: rearrange pipeline by logic (#9970)

* ci: rearrange pipeline by logic

* ci: rename docs script

* fix docker build (#9971)

* Deny unknown fields for chainspec (#9972)

* Add deny_unknown_fields to chainspec

* Add tests and fix existing one

* Remove serde_ignored dependency for chainspec

* Fix rpc test eth chain spec

* Fix starting_nonce_test spec

* Improve block and transaction propagation (#9954)

* Refactor sync to add priority tasks.

* Send priority tasks notifications.

* Propagate blocks, optimize transactions.

* Implement transaction propagation. Use sync_channel.

* Tone down info.

* Prevent deadlock by not waiting forever for sync lock.

* Fix lock order.

* Don't use sync_channel to prevent deadlocks.

* Fix tests.

* Fix unstable peers and slowness in sync (#9967)

* Don't sync all peers after each response

* Update formating

* Fix tests: add `continue_sync` to `Sync_step`

* Update ethcore/sync/src/chain/mod.rs

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

* fix rpc middlewares

* fix Cargo.lock

* json: resolve merge in spec

* rpc: fix starting_nonce_test

* ci: allow nightl job to fail
2018-11-29 10:57:49 +01:00
Thibaut Sardan
5c56fc5023 Backport Beta 2.2.1 (#9905)
* Bump beta to version 2.2.1

* fix: Intermittent failing CI due to addr in use (#9885)

Allow OS to set port at runtime

* Use Weak reference in PubSubClient (#9886)

* Fix json tracer overflow (#9873)

* Fix json tracer overflow

* Replace trace_executed with a direct trace push

* Remove unused variable

* Add test for 5a51

* Remove duplicate json!

* Fix docker script (#9854)


* Dockerfile: change source path of the newly added check_sync.sh (#9869)

* Allow to seal work on latest block (#9876)

* Allow to seal work on latest block.

* Test from @todr to check sealing conditions.

* gitlab-ci: make android release build succeed (#9743)

* use docker cargo config file for android builds

* make android build succeed

* ethcore: use Machine::verify_transaction on parent block (#9900)

* ethcore: use Machine::verify_transaction on parent block

also fixes off-by-one activation of transaction permission contract

* ethcore: clarify call to verify_transaction

* foundation: #6692865, ropsten: #4417537, kovan: #9363457

* Remove rust-toolchain file (#9906)

* EIP-712 implementation (#9631)

* EIP-712 impl

* added more tests

* removed size parsing unwrap

* corrected TYPE_REGEX to disallow zero sized fixed length arrays, replaced LinkedHashSet with IndexSet, added API spec to docs, fixed Type::Byte encoding branch

* use Option<u64> instead of u64 for Type::Array::Length

* replace `.iter()` with  `.values()`

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

* tabify eip712.rs

* use proper comments for docs

* Cargo.lock: revert unrelated changes

* tabify encode.rs

* EIP 191 (#9701)

* added sign_191 rpc method

* fixed hash_structured_data return type

* added ConfirmationPayload::SignMessage for non-prefixed signatures, added tests for sign191

* renamed WithValidator -> PresignedTransaction

* rename applicationData to data in test

* adds docs for EIP191Version, renamed SignRequest to EIP191SignRequest

* light-fetch: Differentiate between out-of-gas/manual throw and use required gas from response on failure (#9824)

* fix start_gas, handle OOG exceptions & NotEnoughGas

* Change START_GAS: 50_000 -> 60_000
* When the `OutOfGas exception` is received then try to double the gas until it succeeds or block gas limit is reached
* When `NotEnoughBasGas error` is received then use the required gas provided in the response

* fix(light-fetch): ensure block_gas_limit is tried

Try the `block_gas_limit` before regard the execution as an error

* Update rpc/src/v1/helpers/light_fetch.rs

Co-Authored-By: niklasad1 <niklasadolfsson1@gmail.com>

* simplify cargo audit

* Use block header for building finality (#9914)

* ci: nuke the gitlab caches (#9855)
2018-11-14 15:23:44 +01:00
Afri Schoedon
5a7e54fb9e version: mark 2.2.0 beta (#9820)
* version: mark 2.2.0 beta

* ci: remove failing tests for android, windows, and macos (#9788)

* ci: remove failing tests for android, windows, and macos

* ci: restore android build jobs

* Move state root verification before gas used (#9841)

* Classic.json Bootnode Update (#9828)

* fix: Update bootnodes list to only responsive nodes

* feat: Add more bootnodes to classic.json list

* feat: Add retested bootnodes

* Implement NoProof for json tests and update tests reference (replaces #9744) (#9814)

* Update test reference.
Block test are really not working so I disabled a few by commenting
directly in source.

* Move ethtest commit cursor.

* Implements 'NoProof' engine from https://github.com/ethereum/tests/issues/464 .

Since tests has been regenerated those one were failing on block
difficulty check.

Update ethereum/tests, waiting for cost fix (block test are still
commented).

* Update tests submodule reference to latest (all test passing except an
identified case).
Fix block reward of constantinople json.

* Restore broken test by using old json tests files.

* Use CanonNoSeal instead of a custom engine, still have to include some
additional tests code.

* Gas upper limit check in json_chain test was bad, moving the test to
verification, the test is running in `verify_header_param`.
Note that test was previously only for ethash, and now for any engine.

* Restore old behavior (gas uper limit only for ethash engine), at the
cost of an additional trait method.

* Proper rpc test fix.

* Update tests submodule, add SStore bug tests.

* Fix json issue tabulation.
Update tests submodule to latest master (lot of new sstore tests
passing)

* Switch ethereum/tests to tag 6.0.0-beta.1 (no tests changes from latest
synch).

* Display hex with separator, use indirection instead of clone for copy
types.
2018-11-02 10:02:46 +01:00
Kirill Fomichev
f8f8bf0fea RPC: parity_allTransactionHashes (#9745)
* rpc: add parity_allTransactionHashes

* Add light_all_transactionst to helpers

* Remove extra parentheses

* Move light_all_transactions to light_fetch

* Remove LightDispatcher import in light_fetch
2018-10-27 09:38:35 +02:00
Andronik Ordian
6643b6a306 Revert "prevent zero networkID (#9763)" (#9815)
This reverts commit 73f08b376f.
2018-10-27 02:53:19 +08:00
Wei Tang
7036ab26d7 Allow zero chain id in EIP155 signing process (#9792)
* Allow zero chain id in EIP155 signing process

* Rename test

* Fix test failure
2018-10-26 22:44:02 +08:00
Azamat M
9b55169251 Add readiness check for docker container (#9804)
* Update Dockerfile

Since parity is built for "mission critical use", I thought other operators may see the need for this.

Adding the `curl` and `jq` commands allows for an extremely simple health check to be usable in container orchestrators.

For example. Here is a health check for a parity docker container running in Kubernetes.

This can be setup as a readiness Probe that would prevent clustered nodes that aren't ready from serving traffic.

```bash
#!/bin/bash

ETH_SYNCING=$(curl -X POST --data '{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":1}' http://localhost:8545 -H 'Content-Type: application/json')
RESULT=$(echo "$ETH_SYNCING | jq -r .result)

if [ "$RESULT" == "false" ]; then
  echo "Parity is ready to start accepting traffic"
  exit 0
else
  echo "Parity is still syncing the blockchain"
  exit 1
fi
```

* add sync check script
2018-10-26 13:51:08 +02:00
Wei Tang
ff13c9c186 Insert dev account before unlocking (#9813) 2018-10-26 19:44:53 +08:00
felix
879e7305ca removed "rustup" & added new runner tag (#9731)
* removed "rustup" & added new runner tag

* exchanged tag "rust-windows" with "windows"

* revert windows tag change
2018-10-26 13:39:44 +02:00
Wei Tang
1ff827b2ea Expose config max-round-blocks-to-import (#9439)
* Expose config max-round-blocks-to-import

* Fix test
2018-10-26 13:21:36 +02:00
André Silva
e7f1204fa4 aura: finalize blocks (#9692)
* aura: emit ancestry actions for finalizing blocks

* aura: refactor is_epoch_end to get finalized blocks as argument

* ethcore: add is_epoch_end_light method to Engine

The full client now tracks finality by querying the engine on each block import,
and it also persists the finalization state to the DB. For the light client
current it doesn't persist finality information and only keeps track of finality
for epoch signals, by calling `is_epoch_end_light`. This method implements the
previously existing logic of building finality for all the blocks in the current
epoch and then checking the finalized blocks against the transition store.

* ethcore: allow finalizing current block

* aura: fix construction of finality proof

* aura: fix warnings

- missing docs for is_epoch_end_light
- unused method unfinalized_hashes in RollingFinality

* aura: fix clone on copy types
2018-10-25 17:33:41 +02:00
Andrew Jones
9a2c4a34ee sync: retry different peer after empty subchain heads response (#9753)
* If no subchain heads then try a different peer

* Add log when useless chain head

* Restrict ChainHead useless peer to ancient blocks

* sync: replace `limit_reorg` with `block_set` condition
2018-10-25 16:56:59 +02:00
Niklas Adolfsson
f4c421f77a fix(light-rpc/parity) : Remove unused client (#9802) 2018-10-24 12:55:24 +02:00
Seun LanLege
fe84718b55 drops support for olympic testnet, closes #9800 (#9801) 2018-10-23 23:54:44 +08:00
Nick Sanders
15d71a01d5 Replace tokio_core with tokio (ring -> 0.13) (#9657)
* Replace `tokio_core` with `tokio`.

* Remove `tokio-core` and replace with `tokio` in

    - `ethcore/stratum`

    - `secret_store`

    - `util/fetch`

    - `util/reactor`

* Bump hyper to 0.12 in

    - `miner`

    - `util/fake-fetch`

    - `util/fetch`

    - `secret_store`

* Bump `jsonrpc-***` to 0.9 in

    - `parity`

    - `ethcore/stratum`

    - `ipfs`

    - `rpc`

    - `rpc_client`

    - `whisper`

* Bump `ring` to 0.13

* Use a more graceful shutdown process in `secret_store` tests.

* Convert some mutexes to rwlocks in `secret_store`.

* Consolidate Tokio Runtime use, remove `CpuPool`.

* Rename and move the `tokio_reactor` crate (`util/reactor`) to
  `tokio_runtime` (`util/runtime`).

* Rename `EventLoop` to `Runtime`.

    - Rename `EventLoop::spawn` to `Runtime::with_default_thread_count`.

    - Add the `Runtime::with_thread_count` method.

    - Rename `Remote` to `Executor`.

* Remove uses of `CpuPool` and spawn all tasks via the `Runtime` executor
  instead.

* Other changes related to `CpuPool` removal:

    - Remove `Reservations::with_pool`. `::new` now takes an `Executor` as an argument.

    - Remove `SenderReservations::with_pool`. `::new` now takes an `Executor` as an argument.
2018-10-23 11:14:45 +02:00
Nick Sanders
abe30f2578 Replace tokio_core with tokio (ring -> 0.13) (#9657)
* Replace `tokio_core` with `tokio`.

* Remove `tokio-core` and replace with `tokio` in

    - `ethcore/stratum`

    - `secret_store`

    - `util/fetch`

    - `util/reactor`

* Bump hyper to 0.12 in

    - `miner`

    - `util/fake-fetch`

    - `util/fetch`

    - `secret_store`

* Bump `jsonrpc-***` to 0.9 in

    - `parity`

    - `ethcore/stratum`

    - `ipfs`

    - `rpc`

    - `rpc_client`

    - `whisper`

* Bump `ring` to 0.13

* Use a more graceful shutdown process in `secret_store` tests.

* Convert some mutexes to rwlocks in `secret_store`.

* Consolidate Tokio Runtime use, remove `CpuPool`.

* Rename and move the `tokio_reactor` crate (`util/reactor`) to
  `tokio_runtime` (`util/runtime`).

* Rename `EventLoop` to `Runtime`.

    - Rename `EventLoop::spawn` to `Runtime::with_default_thread_count`.

    - Add the `Runtime::with_thread_count` method.

    - Rename `Remote` to `Executor`.

* Remove uses of `CpuPool` and spawn all tasks via the `Runtime` executor
  instead.

* Other changes related to `CpuPool` removal:

    - Remove `Reservations::with_pool`. `::new` now takes an `Executor` as an argument.

    - Remove `SenderReservations::with_pool`. `::new` now takes an `Executor` as an argument.
2018-10-22 10:11:24 +02:00
Nick Sanders
fdae48547b Replace tokio_core with tokio (ring -> 0.13) (#9657)
* Replace `tokio_core` with `tokio`.

* Remove `tokio-core` and replace with `tokio` in

    - `ethcore/stratum`

    - `secret_store`

    - `util/fetch`

    - `util/reactor`

* Bump hyper to 0.12 in

    - `miner`

    - `util/fake-fetch`

    - `util/fetch`

    - `secret_store`

* Bump `jsonrpc-***` to 0.9 in

    - `parity`

    - `ethcore/stratum`

    - `ipfs`

    - `rpc`

    - `rpc_client`

    - `whisper`

* Bump `ring` to 0.13

* Use a more graceful shutdown process in `secret_store` tests.

* Convert some mutexes to rwlocks in `secret_store`.

* Consolidate Tokio Runtime use, remove `CpuPool`.

* Rename and move the `tokio_reactor` crate (`util/reactor`) to
  `tokio_runtime` (`util/runtime`).

* Rename `EventLoop` to `Runtime`.

    - Rename `EventLoop::spawn` to `Runtime::with_default_thread_count`.

    - Add the `Runtime::with_thread_count` method.

    - Rename `Remote` to `Executor`.

* Remove uses of `CpuPool` and spawn all tasks via the `Runtime` executor
  instead.

* Other changes related to `CpuPool` removal:

    - Remove `Reservations::with_pool`. `::new` now takes an `Executor` as an argument.

    - Remove `SenderReservations::with_pool`. `::new` now takes an `Executor` as an argument.
2018-10-22 10:09:28 +02:00
Nick Sanders
68ca8df22f Replace tokio_core with tokio (ring -> 0.13) (#9657)
* Replace `tokio_core` with `tokio`.

* Remove `tokio-core` and replace with `tokio` in

    - `ethcore/stratum`

    - `secret_store`

    - `util/fetch`

    - `util/reactor`

* Bump hyper to 0.12 in

    - `miner`

    - `util/fake-fetch`

    - `util/fetch`

    - `secret_store`

* Bump `jsonrpc-***` to 0.9 in

    - `parity`

    - `ethcore/stratum`

    - `ipfs`

    - `rpc`

    - `rpc_client`

    - `whisper`

* Bump `ring` to 0.13

* Use a more graceful shutdown process in `secret_store` tests.

* Convert some mutexes to rwlocks in `secret_store`.

* Consolidate Tokio Runtime use, remove `CpuPool`.

* Rename and move the `tokio_reactor` crate (`util/reactor`) to
  `tokio_runtime` (`util/runtime`).

* Rename `EventLoop` to `Runtime`.

    - Rename `EventLoop::spawn` to `Runtime::with_default_thread_count`.

    - Add the `Runtime::with_thread_count` method.

    - Rename `Remote` to `Executor`.

* Remove uses of `CpuPool` and spawn all tasks via the `Runtime` executor
  instead.

* Other changes related to `CpuPool` removal:

    - Remove `Reservations::with_pool`. `::new` now takes an `Executor` as an argument.

    - Remove `SenderReservations::with_pool`. `::new` now takes an `Executor` as an argument.
2018-10-22 09:40:50 +02:00
HackyMiner
b8da38f4e4 Support eth_chainId RPC method (#9783)
* Support eth_chainId RPC method

 * https://github.com/ethereum/EIPs/pull/695
 * Original PR is #6329

* rpc: remove parity_chainId
2018-10-21 03:13:23 +08:00
Afri Schoedon
1f103ab7f1 ethcore: bump ropsten forkblock checkpoint (#9775) 2018-10-18 15:54:42 +02:00
Afri Schoedon
da6cf33aac docs: changelogs for 2.0.8 and 2.1.3 (#9758)
* docs: add changelog for parity ethereum v2.1.3 beta

* docs: add changelog for parity ethereum v2.0.7 stable
2018-10-17 14:52:11 +02:00
Seun LanLege
73f08b376f prevent zero networkID (#9763)
* prevent zero networkID, closes #8345

Signed-off-by: Seun LanLege <seunlanlege@gmail.com>

* updated networkID of olymic chain spec

Signed-off-by: Seun LanLege <seunlanlege@gmail.com>
2018-10-17 07:47:11 +08:00
Yucong Sun
ed34d1fee7 Skip seal fields count check when --no-seal-check is used (#9757)
* Skip seal fields count check when --no-seal-check is used

* Remove trailing whitespace
2018-10-16 18:24:47 +08:00
André Silva
e9f4f1d13c aura: fix panic on extra_info with unsealed block (#9755)
* aura: fix panic when unsealed block passed to extra_info

* aura: use hex formatting for EmptyStep hashes

* aura: add test for extra_info
2018-10-15 18:05:53 +02:00
Afri Schoedon
e5bb330be5 docs: update changelogs (#9742)
* docs: add changelog for 2.0.7 stable

* docs: add changelog for 2.1.2 beta
2018-10-15 18:01:35 +02:00
Svyatoslav Nikolsky
e23e22cb81 removed extra assert in generation_session_is_removed_when_succeeded (#9738) 2018-10-15 16:02:09 +01:00
Wei Tang
7434026f5f Make checkpoint_storage_at use plain loop instead of recursion (#9734)
* Make checkpoint_storage_at use plain loop instead of recursion

* Add target: "state" to warn!

* Use iterator::Skip
2018-10-15 22:06:56 +08:00
Wei Tang
5319d33bc6 Use signed 256-bit integer for sstore gas refund substate (#9746)
* Add signed refund

* Use signed 256-bit integer for sstore gas refund substate

* Fix tests

* Remove signed mod and use i128 directly

* Fix evm test case casting

* Fix jsontests ext signature
2018-10-15 17:09:55 +08:00
gabriel klawitter
702311b6b2 heads ref not present for branches beta and stable (#9741) 2018-10-12 13:45:28 +02:00
Yohan Graterol
2511bc20e0 Add Callisto support (#9534)
* Add Callisto Mainnet support

* Add new bootnodes

* Remove merge failure

* EIP-649 removed

* Remove eip649Reward

* Modify difficultyBombDelays

* Callisto reward smart contract

* Remove ethash params

* Fix merge
2018-10-11 11:03:57 +02:00
Wei Tang
ce5a6eabae Add --force to cargo audit install script (#9735) 2018-10-11 10:53:00 +02:00
Marek Kotewicz
581cd97ba1 remove unused expired value from Handshake (#9732) 2018-10-10 23:17:17 +02:00
Thibaut Sardan
fa2f99641f Add hardcoded headers (#9730)
* add foundation hardcoded header #6486017

* add ropsten hardcoded headers #4202497

* add kovan hardcoded headers #9023489
2018-10-10 17:37:10 +02:00
Andronik Ordian
c40f7db1ab produce portable binaries (#9725) 2018-10-10 14:52:15 +02:00
gabriel klawitter
be1363e943 gitlab ci: releasable_branches: change variables condition to schedule (#9729) 2018-10-10 14:51:36 +02:00
David
c313039526 Update a few parity-common dependencies (#9663)
* Update a few parity-common dependencies

* cleanup

* cleanup

* revert update of ethereum/tests

* better reporting of network rlp errors

* Use rlp 0.3.0-beta.1

* fix util function get_dummy_blocks

* Already a Vec

* encode_list returns vec already

* Address grumble

* No need for betas

* Fix double spaces
2018-10-09 22:07:25 +02:00
Vadim Arasev
73db5dda8c HF in POA Core (2018-10-22) (#9724)
https://github.com/poanetwork/poa-chain-spec/pull/87
2018-10-09 17:17:39 +02:00
gabriel klawitter
5a8fb77fb2 Schedule nightly builds (#9717)
* introduce SCHEDULE_TAG variable for gitlab scheduled nightly builds

* add refs for complex only statement in .gitlab-ci.yml
2018-10-09 15:32:07 +02:00
Andrew Jones
4b6ebcbb61 Fix ancient blocks sync (#9531)
* Log block set in block_sync for easier debugging

* logging macros

* Match no args in sync logging macros

* Add QueueFull error

* Only allow importing headers if the first matches requested

* WIP

* Test for chain head gaps and log

* Calc distance even with 2 heads

* Revert previous commits, preparing simple fix

This reverts commit 5f38aa885b22ebb0e3a1d60120cea69f9f322628.

* Reject headers with no gaps when ChainHead

* Reset block sync download when queue full

* Simplify check for subchain heads

* Add comment to explain subchain heads filter

* Fix is_subchain_heads check and comment

* Prevent premature round completion after restart

This is a problem on mainnet where multiple stale peer requests will
force many rounds to complete quickly, forcing the retraction.

* Reset stale old blocks request after queue full

* Revert "Reject headers with no gaps when ChainHead"

This reverts commit 0eb865539e5dee37ab34f168f5fb643300de5ace.

* Add BlockSet to BlockDownloader logging

Currently it is difficult to debug this because there are two instances,
one for OldBlocks and one for NewBlocks. This adds the BlockSet to all
log messages for easy log filtering.

* Reset OldBlocks download from last enqueued

Previously when the ancient block queue was full it would restart the
download from the last imported block, so the ones still in the queue would be
redownloaded. Keeping the existing downloader instance and just
resetting it will start again from the last enqueued block.:wq

* Ignore expired Body and Receipt requests

* Log when ancient block download being restarted

* Only request old blocks from peers with >= difficulty

https://github.com/paritytech/parity-ethereum/pull/9226 might be too
permissive and causing the behaviour of the retraction soon after the
fork block. With this change the peer difficulty has to be greater than
or euqal to our syncing difficulty, so should still fix
https://github.com/paritytech/parity-ethereum/issues/9225

* Some logging and clear stalled blocks head

* Revert "Some logging and clear stalled blocks head"

This reverts commit 757641d9b817ae8b63fec684759b0815af9c4d0e.

* Reset stalled header if useless more than once

* Store useless headers in HashSet

* Add sync target to logging macro

* Don't disable useless peer and fix log macro

* Clear useless headers on reset and comments

* Use custom error for collecting blocks

Previously we resued BlockImportError, however only the Invalid case and
this made little sense with the QueueFull error.

* Remove blank line

* Test for reset sync after consecutive useless headers

* Don't reset after consecutive headers when chain head

* Delete commented out imports

* Return DownloadAction from collect_blocks instead of error

* Don't reset after round complete, was causing test hangs

* Add comment explaining reset after useless

* Replace HashSet with counter for useless headers

* Refactor sync reset on bad block/queue full

* Add missing target for log message

* Fix compiler errors and test after merge

* ethcore: revert ethereum tests submodule update
2018-10-09 15:31:40 +02:00
Afri Schoedon
bc056c41bc CI: Skip docs job for nightly (#9693)
* ci: force-tag wiki changes

* ci: force-tag wiki changes

* ci: skip docs job for master and nightly

* ci: revert docs job checking for nightly tag

* ci: exclude docs job from nightly builds in gitlab script
2018-10-09 12:50:31 +02:00
Niklas Adolfsson
5b54442a48 fix (light/provider) : Make read_only executions read-only (#9591)
* `ExecutionsRequest` from light-clients as read-only

This changes so all `ExecutionRequests` from light-clients are executed
as read-only which the `virtual``flag == true ensures.

This boost up the current transaction to always succeed

Note, this only affects `eth_estimateGas` and `eth_call` AFAIK.

* grumbles(revert renaming) : TransactionProof

* grumbles(trace) : remove incorrect trace

* grumbles(state/prove_tx) : explicit `virt`

Remove the boolean flag to determine that a `state::prove_transaction`
whether it should be executed in a virtual context or not.

Because of that also rename the function to
`state::prove_transction_virtual` to make more clear
2018-10-08 21:30:46 +02:00
André Silva
dc14cce7a9 ethcore: fix detection of major import (#9552)
* sync: set state to idle after sync is completed

* sync: refactor sync reset
2018-10-08 12:04:38 +01:00
David
4f278ba715 return 0 on error (#9705) 2018-10-05 12:23:04 +02:00
Afri Schoedon
1036fcca36 ethcore: delay ropsten hardfork (#9704) 2018-10-05 15:09:42 +08:00
Marek Kotewicz
6b286a5dee make instantSeal engine backwards compatible, closes #9696 (#9700) 2018-10-04 15:08:20 +02:00
Wei Tang
c8ae675b95 Implement CREATE2 gas changes and fix some potential overflowing (#9694)
* Implement CREATE2 gas changes and fix some potential overflowing

* Ignore create2 state tests

* Split CREATE and CREATE2 in gasometer

* Generalize rounding (x + 31) / 32 to to_word_size
2018-10-04 20:50:18 +08:00
Tomasz Drwięga
4186467129 Don't hash the init_code of CREATE. (#9688) 2018-10-04 12:32:04 +01:00
André Silva
726884afcb ethcore: minor optimization of modexp by using LR exponentiation (#9697) 2018-10-04 12:29:53 +01:00
Marek Kotewicz
5a2f3e700b removed redundant clone before each block import (#9683)
* removed redundant clone before each block import

* Fix a trival typo
2018-10-04 01:44:58 +08:00
EOS Classic
911fc74346 Add Foundation Bootnodes (#9666) 2018-10-04 00:01:22 +08:00
Lorenzo Manacorda
1388f4d27e Docker: run as parity user (#9689) 2018-10-03 13:10:05 +01:00
André Silva
5b87327a43 ethcore: mcip3 block reward contract (#9605)
* Use static call and apparent value transfer for block reward contract code

* ethcore: implement musicoin block reward logic with contract

* ethcore: update musicoin block reward contract bytecode

* ethcore: add comment with source of musicoin block reward contract

* ethcore: remove unused mcip6_byz chain spec
2018-10-03 12:44:43 +01:00
Jim Posen
2fc1679886 Verify block syncing responses against requests (#9670)
* sync: Validate received BlockHeaders packets against stored request.

* sync: Validate received BlockBodies and BlockReceipts.

* sync: Fix broken tests.

* sync: Unit tests for BlockDownloader::import_headers.

* sync: Unit tests for import_{bodies,receipts}.

* tests: Add missing method doc.
2018-10-03 18:35:10 +08:00
YihaoPeng
7ba5652bea Add a new RPC parity_submitWorkDetail similar eth_submitWork but return block hash (#9404)
* add a new RPC `eth_submitWorkDetail`similar `eth_submitWork`.

It has more details (block hash, error message, and more in future)
in its response and not only the `true` or `false`.

* move RPC submitWorkDetail from namespace eth_ to parity_

* remove SubmitDetailResult type; submitWorkDetail return a error when failed

* change error message of RPC error `cannot_submit_work`.

* remove double imported H256.

* put submit_work_detail into a helper to avoid the duplicate codes.
2018-10-03 03:02:48 +08:00
Wei Tang
1e9aebbc86 Resumable EVM and heap-allocated callstack (#9360)
* Add new Vm trappable interface

* Exec/Resume interface

* Basic implementation of CallCreateExecutive

* Implement resume_call and resume_create for executive

* Move convertion to call/create result to separate function

* Implement consume that converts resumable to non-resumable

* Use consume for Executive::call/create

* Resumable EVM

* Implement tracing mode without needing subtracers

* Implement vmtracer so it doesn't require extra structs for subtracing

* Use the new tracing mode in executive

* Fix most of the linting errors for cargo build

* Add the concept of stack_depth

* Add back crossbeam

* Fix some test compile

* Fix prefix address test

* Fix evm crate tests

* Fix wasm crate test compile

* Fix wasm runner compile

* Fix jsontests compile

* Fix evmbin compile

* Fix an issue with create nonce and better vm tracing interface

* Fix linting

* Fix evmbin compile

* Fix unconfirmed_substate and static_flag

* Fix an issue in create address logic

* Fix top-level tracing

* Handle builtin tracing

* Fix suicide and reward tracing index stack

* Fix an issue where trap conflicts with tracing

* Fix an issue in parent step vm tracing

* Fix revert tracing

* Fix evmbin tests

* Remove params clone

* Fix TODO proofs

* Fix jsontests compile

* Fix evmbin merge issue

* Fix wasm merge issue

* Fix wasm test

* Fix ethcore merge warnings

* Fix evmbin compile

* Better expect messages and add some trace::skip_one asserts
2018-10-02 22:33:19 +08:00
Marek Kotewicz
61ec361182 update parity-wordlist library (#9682) 2018-10-02 13:50:50 +01:00
Afri Schoedon
7781cbbc57 CI: Remove unnecessary pipes (#9681)
* ci: reduce gitlab pipelines significantly

* ci: build pipeline for PR

* ci: remove dead weight

* ci: remove github release script

* ci: remove forever broken aura tests

* ci: add random stuff to the end of the pipes

* ci: add wind and mac to the end of the pipe

* ci: remove snap artifacts

* ci: (re)move dockerfiles

* ci: clarify job names

* ci: add cargo audit job

* ci: make audit script executable

* ci: ignore snap and docker files for rust check

* ci: simplify audit script

* ci: rename misc to optional

* ci: add publish script to releaseable branches

* ci: more verbose cp command for windows build

* ci: fix weird binary checksum logic in push script

* ci: fix regex in push script for windows

* ci: simplify gitlab caching

* docs: align README with ci changes

* ci: specify default cargo target dir

* ci: print verbose environment

* ci: proper naming of scripts

* ci: restore docker files

* ci: use docker hub file

* ci: use cargo home instead of cargo target dir

* ci: touch random rust file to trigger real builds

* ci: set cargo target dir for audit script

* ci: remove temp file

* ci: don't export the cargo target dir in the audit script

* ci: fix windows unbound variable

* docs: fix gitlab badge path

* rename deprecated gitlab ci variables

https://docs.gitlab.com/ee/ci/variables/#9-0-renaming

* ci: fix git compare for nightly builds

* test: skip c++ example for all platforms but linux

* ci: add random rust file to trigger tests

* ci: remove random rust file

* disable cpp lib test for mac, win and beta (#9686)
2018-10-02 00:03:58 +01:00
gabriel klawitter
f3b806b471 test.sh: use cargo --target for platforms other than linux, win or mac (#9650)
* test.sh: use cargo --target for platforms other than linux, win or mac

* drying test.sh script

* run tests only when not cross-compiling

* quote variable value
2018-10-01 11:55:17 +01:00
Andronik Ordian
6496405f30 ci: fix push script (#9679)
* ci: fix push script

* Fix copying & running on windows.
2018-10-01 10:13:31 +01:00
Afri Schoedon
85a6dc5e8c Hardfork the testnets (#9562)
* ethcore: propose hardfork block number 4230000 for ropsten

* ethcore: propose hardfork block number 9000000 for kovan

* ethcore: enable kip-4 and kip-6 on kovan

* etcore: bump kovan hardfork to block 9.2M

* ethcore: fix ropsten constantinople block number to 4.2M

* ethcore: disable difficulty_test_ropsten until ethereum/tests are updated upstream
2018-09-30 13:44:17 +01:00
Tomasz Drwięga
856bbfc9c8 Calculate sha3 instead of sha256 for push-release. (#9673)
* Calculate sha3 instead of sha256 for push-release.

* Add pushes to the script.
2018-09-30 12:42:49 +01:00
Marek Kotewicz
ebaa43fa4c ethcore-io retries failed work steal (#9651)
* ethcore-io uses newer version of crossbeam && retries failed work steal

* ethcore-io non-mio service uses newer crossbeam
2018-09-29 21:25:16 +01:00
Andronik Ordian
2d44b3ebea fix(light_fetch): avoid race with BlockNumber::Latest (#9665) 2018-09-29 21:22:36 +01:00
ddorgan
984493db30 Test fix for windows cache name... (#9658)
* Test fix for windows cache name...

* Fix variable name.
2018-09-28 18:52:15 +01:00
Niklas Adolfsson
47848769ff refactor(fetch) : light use only one DNS thread (#9647)
* refactor(fetch) : light use only one `DNS` thread

* grumbles(fetch) : pass number of threads directly
2018-09-28 14:26:38 +01:00
cheme
a8f6f5b974 ethereum libfuzzer integration small change (#9547)
* Minor changes for ethereum libfuzzer.
2018-09-27 17:17:23 +02:00
André Silva
1e13f474cb cli: remove reference to --no-ui in --unlock flag help (#9616) 2018-09-27 11:24:34 +01:00
Denis S. Soldatov aka General-Beck
c69c3a9a46 remove master from releasable branches (#9655)
* remove master from releasable branches

need backporting in beta 
fix https://gitlab.parity.io/parity/parity-ethereum/-/jobs/101065 etc

* add except for snap packages for master
2018-09-27 11:21:48 +01:00
Niklas Adolfsson
3216b143c2 ethcore/VerificationQueue don't spawn up extra worker-threads when explictly specified not to (#9620)
* VerificationQueue don't spawn up extra threads

In the verification queue we spawn up worker threads to do the work.
However, if `num-verifiers` is specified we still spawn the maximum
number of threads which consume extra memory.

There is one catch though when `--scale-verifiers` is specified then
we can't do it because all threads are created upon initilization AFAIK.

In my opinion, is doesn't to use both `num-verifiers` and
`scale-verifiers` they are kind of contradictory!

* Fix nits in logic and add tests for verification

* refactor(verification queue) - rm hardcoded const

* Address grumbles in new tests
* Remove hardcoded `MAX_VERIFIERS` constant and replace it by relying
entirely on `num_cpu` crate instead inorder to support CPUs that have
more cores/logical cores
2018-09-26 15:11:50 +01:00
Tomasz Drwięga
cc963d42a0 RPC: parity_getBlockReceipts (#9527)
* Block receipts RPC.

* Use lazy evaluation of block receipts (ecrecover).

* Optimize transaction_receipt to prevent performance regression.

* Fix RPC grumbles.

* Add block & transaction receipt tests.

* Fix conversion to block id.
2018-09-25 18:06:14 +01:00
Niklas Adolfsson
3f95a62e4f Remove unused dependencies (#9589)
Remove unused dependencies and move `rustc-hex` to tests because it is
only used in tests
2018-09-25 15:27:27 +02:00
Marek Kotewicz
7f9a9e2e82 ignore key_server_cluster randomly failing tests (#9639)
* ignore key_server_cluster randomly failing tests, related to #9635

* added explanation comment to test #[ignore]
2018-09-25 14:15:35 +01:00
André Silva
375ecd4ada ethcore: handle vm exception when estimating gas (#9615) 2018-09-25 12:35:07 +01:00
Marek Kotewicz
8875dccd11 fix bad-block reporting no reason (#9638) 2018-09-25 18:55:24 +08:00
Wei Tang
4c2301fdf6 Use static call and apparent value transfer for block reward contract code (#9603) 2018-09-25 11:39:27 +01:00
Vadim Arasev
346594c406 HF in POA Sokol (2018-09-19) (#9607)
https://github.com/poanetwork/poa-chain-spec/pull/86
2018-09-25 12:25:55 +02:00
Marek Kotewicz
2609e2db5c bump smallvec to 0.6 in ethcore-light, ethstore and whisper (#9588)
* bump smallvec to 0.6 in ethcore-light, ethstore and whisper

* bump transaction-pool

* Fix test.
2018-09-25 12:24:59 +02:00
cheme
692d5b4e08 Add constantinople conf to EvmTestClient. (#9570)
* Add constantinople conf to EvmTestClient.

* Skip some test to update submodule etheureum/tests submodule to latest.

* Put skipping 'under issue' test behind a feature.

* Change blockReward for const-test to pass ethereum/tests

* Update tests to new constantinple definition (change of reward at block
5).
Switch 'reference' to string, that way we can include issues from others
repo (more flexible)Update tests to new constantinple definition (change
of reward at block 5).
Switch 'reference' to string, that way we can include issues from others
repo (more flexible).

* Fix modexp and bn128_mul gas prices in chain config

* Changes `run_test_path` method to append its directory results (without
that it stop testing at the first file failure).
Add some missing tests.
Add skip for those (block create2 is one hundred percent false but on
hive we can see that geth and aleth got similar issue for this item).

* retab current.json

* Update reference to parity issue for failing tests.
2018-09-25 12:24:40 +02:00
Andronik Ordian
c4af7464e5 fix(network): don't disconnect reserved peers (#9608)
The priority of && and || was borked.
2018-09-25 10:59:21 +01:00
Marek Kotewicz
5a1dc3eb8a fix failing node-table tests on mac os, closes #9632 (#9633) 2018-09-24 21:51:16 +01:00
EOS Classic
adcbfcf8d6 Update ropsten.json (#9602) 2018-09-24 11:30:01 +01:00
Marek Kotewicz
b57607e7d3 simplify ethcore errors by removing BlockImportError (#9593) 2018-09-24 11:28:54 +01:00
Marek Kotewicz
2f159d4f45 fix windows compilation, replaces #9561 (#9621)
* fix windows compilation, replaces #9561

* tokio-named-pipes
2018-09-24 11:27:51 +01:00
gabriel klawitter
93e1040d07 master: rpc-docs set github token (#9610) 2018-09-21 13:02:15 +02:00
Afri Schoedon
403c07c305 docs: add changelogs for 1.11.10, 1.11.11, 2.0.3, 2.0.4, 2.0.5, 2.0.6, 2.1.0, and 2.1.1 (#9554)
* docs: prepare changelog for 2.1.0 beta

* docs: move changelog for 2.0.x to stable

* docs: add changelog for legacy 1.11.x

* docs: add release notes for 2.0.x beta releases

* docs: mark 1.11 end of life

* docs: prepare release notes for 2.0.5 stable

* docs: prepare release notes for 2.1.0 beta

* ci: ignore docs in tests

* docs: bump version in readme

* docs: update changelog for 2.0.5 stable

* docs: update changelog for 2.1.0 beta

* docs: update changelog for 2.1.0 beta

* docs: remove eip86 from release notes

* docs: update changelog for 2.1.0

* docs: add changelog for 2.1.1 and 2.0.6

* docs: correct spelling of certain words in the latest changelog
2018-09-20 10:59:15 +02:00
Andronik Ordian
6253308e2e docs(rpc): annotate tag with the provided message (#9601) 2018-09-19 20:23:47 +02:00
Afri Schoedon
33a014013a ci: fix regex 🙄 (#9597) 2018-09-19 18:57:59 +02:00
Denis S. Soldatov aka General-Beck
4637215ab2 Remove snapcraft clean (#9585)
* Revert " add snapcraft package image (master) (#9584)"

This reverts commit ceaedbbd7f.

* Update package-snap.sh

* Update .gitlab-ci.yml
2018-09-18 15:34:24 +02:00
Denis S. Soldatov aka General-Beck
ceaedbbd7f add snapcraft package image (master) (#9584) 2018-09-18 14:39:27 +02:00
Andronik Ordian
52f8b1a1d7 docs(rpc): push the branch along with tags (#9578)
* docs(rpc): push the branch along with tags

* ci: remove old rpc docs script
2018-09-18 08:54:50 +02:00
Thibaut Sardan
e6d1250185 Fix typo for jsonrpc-threads flag (#9574) 2018-09-18 00:56:33 +08:00
Wei Tang
d04e5e49d0 Fix informant compile (#9571) 2018-09-17 16:16:49 +02:00
EOS Classic
a72436f330 Added ropsten bootnodes (#9569)
from @eosclassicteam with ❤️
2018-09-17 12:16:32 +02:00
EOS Classic
467403f437 Increase Gas-floor-target and Gas Cap (#9564)
+ Gas-floor-target increased to 8M by default

+ Gas-cap increased to 10M by default
2018-09-17 08:33:00 +02:00
gabriel klawitter
bbaac0c6a9 while working on the platform tests make them non-breaking (#9563)
* while working on the platform tests make them non-critical

* ci: unify test stage job names and torelate more failures

* ci: restore valid yaml

* ci: allow beta and nightly rust builds to fail
2018-09-15 13:43:19 +02:00
Nicolas Gotchac
753fd4bda3 Improve P2P discovery (#9526)
* Add `target` to Rust traces

* network-devp2p: Don't remove discovery peer in main sync

* network-p2p: Refresh discovery more often

* Update Peer discovery protocol

* Run discovery more often when not enough nodes connected

* Start the first discovery early

* Update fast discovery rate

* Fix tests

* Fix `ping` tests

* Fixing remote Node address ; adding PingPong round

* Fix tests: update new +1 PingPong round

* Increase slow Discovery rate
Check in flight FindNode before pings

* Add `deprecated` to deprecated_echo_hash

* Refactor `discovery_round` branching
2018-09-14 22:18:03 +02:00
gabriel klawitter
57d2c8c94a move dockerfile for android build container to scripts repo (#9560) 2018-09-14 16:16:36 +02:00
gabriel klawitter
870ec89e9a Simultaneous platform tests WIP (#9557)
* look into commit changes

* look into commit changes ii

* all on test

* build only_releaseable_branches for platforms

* allow failure for check during development

* windows test typo

* fix sh for windows

* remove check stage again

* debug macos platform
2018-09-14 15:55:14 +02:00
Marek Kotewicz
0c3b70f2fb update ethabi-derive, serde, serde_json, serde_derive, syn && quote (#9553) 2018-09-14 03:37:28 +08:00
Andronik Ordian
7a367698fe ci: fix rpc docs generation 2 (#9550) 2018-09-13 14:36:44 +02:00
Afri Schoedon
c77e99814b ci: always run build pipelines for win, mac, linux, and android (#9537)
* ci: always run build pipelines for win, mac, linux, and android

* ci: always run build pipelines for win, mac, linux, and android

* ci: disallow failure for publish scripts

* ci: enable tests on master

* ci: run tests in debug mode to speed things up

* ci: only build windows, darwin, and android targets on PRs

* ci: reenable darwin and android pipelines on PR

* ci: revert tests to run in release mode
2018-09-13 13:15:15 +02:00
Nicolas Gotchac
4ddd69cc55 Multithreaded snapshot creation (#9239)
* Add Progress to Snapshot Secondary chunks creation

* Use half of CPUs to multithread snapshot creation

* Use env var to define number of threads

* info to debug logs

* Add Snapshot threads as CLI option

* Randomize chunks per thread

* Remove randomness, add debugging

* Add warning

* Add tracing

* Use parity-common fix seek branch

* Fix log

* Fix tests

* Fix tests

* PR Grumbles

* PR Grumble II

* Update Cargo.lock

* PR Grumbles

* Default snapshot threads to half number of CPUs

* Fix default snapshot threads // min 1
2018-09-13 12:58:49 +02:00
Marek Kotewicz
ef4a61c769 new ethabi (#9511)
* new ethabi migration in progress

* parity migrated to new ethabi

* migrated secred-store to new ethabi

* bump ethabi to 6.0

* fixed review suggestions
2018-09-13 11:04:39 +02:00
Tomasz Drwięga
7dfb5ff5bd Remove initial token for WS. (#9545) 2018-09-13 10:58:52 +02:00
Marek Kotewicz
6b391312ab net_version caches network_id to avoid redundant aquire of sync read lock (#9544)
* net_version caches network_id to avoid redundant aquire of sync read lock, #8746

* use lower_hex display formatting for net_peerCount rpc method
2018-09-13 10:16:24 +02:00
gabriel klawitter
6e62d77e4d correct before_script for nightly build versions (#9543)
- fix gitlab array of strings syntax error
- get proper commit id
- avoid colon in stings
2018-09-12 17:46:56 +03:00
Afri Schoedon
0281cca9af deps: bump kvdb-rocksdb to 0.1.4 (#9539) 2018-09-12 13:23:09 +02:00
Wei Tang
018e2403b1 state: test when contract creation fails, old storage values should re-appear (#9532)
Because more tests won't hurt. :)

Add a test case for https://github.com/ethereum/py-evm/pull/1224#issuecomment-418775512 where if contract creation fails, old storage values (if ever existed) should re-appear.
2018-09-12 11:42:09 +01:00
cheme
61f4534e2a Allow dropping light client RPC query with no results (#9318)
* OnDemand no longer loop until there is a query.
All peer known at the time will be queried, and the query fail if all
return no reply.
Returning the failure is done through an empty Vec of reply (the type
of the oneshot channel remains unchanged).
Before this commit the query were send randomly to any peer until there
is a reply (for a query that got no result it was an issue, for other
queries it was quering multiple times the same peers).
After this commit the first query is random but next queries
follows hashmap iterator order.

Test no_capability was broken by this commit (the pending query was
removed).

* OnDemand no longer loop until there is a query.
All peer known at the time will be queried, and the query fail if all
return no reply.
Returning the failure is done through an empty Vec of reply (the type
of the oneshot channel remains unchanged).
Before this commit the query were send randomly to any peer until there
is a reply (for a query that got no result it was an issue, for other
queries it was quering multiple times the same peers).
After this commit the first query is random but next queries
follows hashmap iterator order.

Test no_capability was broken by this commit (the pending query was
removed). If adding some kind of timeout mechanism it could be restored.

* Comment plus better field names.

* No panick on dropped oneshot channel.

* Use Set to avoid counter heuristic

* Cli option `on_demand_nb_retry` for maximum number of retry when doing
on demand query in light client.

* Missing test update for previous commit

* Add a timeout (only when there is no peer to query), that way we do not
set number of query to minimum current number peer or configured number
of query : that way capability test was restored.

* Adding an error type for on_demand, it helps having variant of error
reported at rpc level : choice of rpc error code error might not be
right.

* Duration as constant is nice

* Switch to duration in main too

* Fix indentation (sorry for that).

* Fix error management (bad merge in previous commit)

* Lots of english corrections, major change on the new command parameters :
 - use standard '-' instead of '_'
 - renaming nb_retry params to 'on-demand-retry-count'
2018-09-12 11:47:01 +02:00
Afri Schoedon
69667317c1 Bump master to 2.2.0 (#9517)
* parity-version: bump master to 2.2.0

* ci: update branch version references

* docker: release master to latest

* deps: bump fs-swap to 0.2.4
2018-09-12 11:32:05 +02:00
Wei Tang
530aac0682 Enable all Constantinople hard fork changes in constantinople_test.json (#9505)
* Enable all Constantinople hard fork changes in constantinople_test.json

* Address grumbles

* Remove EIP-210 activation

* 8m -> 5m

* Temporarily add back eip210 transition so we can get test passed

* Add eip210_test and remove eip210 transition from const_test
2018-09-12 02:08:23 +08:00
Niklas Adolfsson
6e7d8f90b5 [light] Validate account balance before importing transactions (#9417)
* `light::verify_transaction` basic tx validation

* update wasm tests

* Provide `cached_nonce` in `parity_next_nonce` RPC

* nits

* Improve error handeling

Two separate errors for distinguishing between `account not found` and
`insufficient balance`. However, when `next_nonce()` is called and the
account is not found then provide `local_best_next_nonce`!

* Ensure only one n/w request is performed

Refactored to code again:
* Removed `fn cached_next_nonce`
* Removed extra n/w request in `sign` to check balance
* Refactored `fill_optional_field` to request nonce and check account balance

* nits

* grumbles needless clone

* Prevent integer overflow with saturating add & mul

* Call `sign_transaction()` directly from `sign()`

Because the change in `fill_optional_fields` always fill the nonce it is
now possible to call `sign_transaction` directly instead of creating a
`ProspectiveSigner` "object".
2018-09-11 19:20:59 +02:00
cheme
65bf1086a2 In create memory calculation is the same for create2 because the additional parameter was popped before. (#9522) 2018-09-11 23:47:26 +08:00
cheme
98220442b4 Update patricia trie to 0.2.2 (#9525)
* Update patricia trie to 0.2.2 crates. Default dependencies on minor
version only.

* Putting back ethereum tests to the right commit
2018-09-11 16:20:26 +02:00
Hernando Castano
3c3d2ef2b9 Replace hardcoded JSON with serde json! macro (#9489)
* Replace hardcoded JSON with serde json! macro

* Use "{:#x}" formatter instead of "0x{:x}"

* Sort fields of JSON test strings alphabetically

* Stop escaping new lines in evmbin JSON errors

* Remove unnecessary 'to_string()' calls

* Add test with non-empty storage values
2018-09-11 11:36:38 +02:00
gabriel klawitter
67066eb32a fix typo in version string (#9516) 2018-09-11 11:31:25 +02:00
318 changed files with 11712 additions and 6214 deletions

View File

@@ -9,16 +9,8 @@ image: parity/rust:gitlab-ci
variables:
CI_SERVER_NAME: "GitLab CI"
CARGO_HOME: "${CI_PROJECT_DIR}/.cargo"
BUILD_TARGET: ubuntu
BUILD_ARCH: amd64
CARGO_TARGET: x86_64-unknown-linux-gnu
cache:
key: "${CI_JOB_NAME}"
paths:
- ./target
- ./.cargo
.releaseable_branches: # list of git refs for building GitLab artifacts (think "pre-release binaries")
only: &releaseable_branches
- stable
@@ -26,9 +18,10 @@ cache:
- tags
- schedules
.collect_artifacts: &collect_artifacts
artifacts:
name: "${CI_JOB_NAME}_${CI_COMMIT_REF_NAME}"
name: "${CI_JOB_NAME}_${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}"
when: on_success
expire_in: 1 mos
paths:
@@ -38,7 +31,7 @@ cache:
- VERSION="$(sed -r -n '1,/^version/s/^version = "([^"]+)".*$/\1/p' Cargo.toml)"
- DATE_STR="$(date +%Y%m%d)"
- ID_SHORT="$(echo ${CI_COMMIT_SHA} | cut -c 1-7)"
- test "${CI_COMMIT_REF_NAME}" = "nightly" && VERSION="${VERSION}-${ID_SHORT}-${DATE_STR}"
- test "${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}" = "nightly" && VERSION="${VERSION}-${ID_SHORT}-${DATE_STR}"
- export VERSION
- echo "Version = ${VERSION}"
@@ -51,6 +44,13 @@ test-linux:
tags:
- rust-stable
test-audit:
stage: test
script:
- scripts/gitlab/cargo-audit.sh
tags:
- rust-stable
build-linux:
stage: build
only: *releaseable_branches
@@ -111,25 +111,18 @@ publish-awss3:
tags:
- shell
docs-jsonrpc:
stage: optional
publish-docs:
stage: publish
only:
- tags
except:
- nightly
cache: {}
script:
- scripts/gitlab/docs-jsonrpc.sh
- scripts/gitlab/publish-docs.sh
tags:
- shell
cargo-audit:
stage: optional
script:
- scripts/gitlab/cargo-audit.sh
tags:
- rust-stable
build-android:
stage: optional
image: parity/rust-android:gitlab-ci
@@ -139,6 +132,7 @@ build-android:
- scripts/gitlab/build-unix.sh
tags:
- rust-arm
allow_failure: true
test-beta:
stage: optional
@@ -148,6 +142,7 @@ test-beta:
- scripts/gitlab/test-all.sh beta
tags:
- rust-beta
allow_failure: true
test-nightly:
stage: optional
@@ -157,3 +152,4 @@ test-nightly:
- scripts/gitlab/test-all.sh nightly
tags:
- rust-nightly
allow_failure: true

File diff suppressed because it is too large Load Diff

1603
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.1.5"
version = "2.2.2"
license = "GPL-3.0"
authors = ["Parity Technologies <admin@parity.io>"]
@@ -28,10 +28,9 @@ serde = "1.0"
serde_json = "1.0"
serde_derive = "1.0"
futures = "0.1"
futures-cpupool = "0.1"
fdlimit = "0.1"
ctrlc = { git = "https://github.com/paritytech/rust-ctrlc.git" }
jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.11" }
jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-2.2" }
ethcore = { path = "ethcore", features = ["parity"] }
parity-bytes = "0.1"
ethcore-io = { path = "util/io" }
@@ -46,12 +45,12 @@ ethcore-transaction = { path = "ethcore/transaction" }
ethereum-types = "0.4"
node-filter = { path = "ethcore/node_filter" }
ethkey = { path = "ethkey" }
rlp = { version = "0.2.4", features = ["ethereum"] }
rlp = { version = "0.3.0", features = ["ethereum"] }
rpc-cli = { path = "rpc_cli" }
parity-hash-fetch = { path = "hash-fetch" }
parity-ipfs-api = { path = "ipfs" }
parity-local-store = { path = "local-store" }
parity-reactor = { path = "util/reactor" }
parity-runtime = { path = "util/runtime" }
parity-rpc = { path = "rpc" }
parity-rpc-client = { path = "rpc_client" }
parity-updater = { path = "updater" }
@@ -89,6 +88,7 @@ daemonize = { git = "https://github.com/paritytech/daemonize" }
[features]
miner-debug = ["ethcore/miner-debug"]
json-tests = ["ethcore/json-tests"]
ci-skip-issue = ["ethcore/ci-skip-issue"]
test-heavy = ["ethcore/test-heavy"]
evm-debug = ["ethcore/evm-debug"]
evm-debug-tests = ["ethcore/evm-debug-tests"]
@@ -137,6 +137,3 @@ members = [
"util/patricia-trie-ethereum",
"util/fastmap",
]
[patch.crates-io]
ring = { git = "https://github.com/paritytech/ring" }

View File

@@ -6,4 +6,3 @@ authors = ["Marek Kotewicz <marek@parity.io>"]
[dependencies]
ethjson = { path = "../json" }
serde_json = "1.0"
serde_ignored = "0.0.4"

View File

@@ -15,10 +15,8 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
extern crate serde_json;
extern crate serde_ignored;
extern crate ethjson;
use std::collections::BTreeSet;
use std::{fs, env, process};
use ethjson::spec::Spec;
@@ -41,24 +39,11 @@ fn main() {
Err(_) => quit(&format!("{} could not be opened", path)),
};
let mut unused = BTreeSet::new();
let mut deserializer = serde_json::Deserializer::from_reader(file);
let spec: Result<Spec, _> = serde_ignored::deserialize(&mut deserializer, |field| {
unused.insert(field.to_string());
});
let spec: Result<Spec, _> = serde_json::from_reader(file);
if let Err(err) = spec {
quit(&format!("{} {}", path, err.to_string()));
}
if !unused.is_empty() {
let err = unused.into_iter()
.map(|field| format!("{} unexpected field `{}`", path, field))
.collect::<Vec<_>>()
.join("\n");
quit(&err);
}
println!("{} is valid", path);
}

View File

@@ -1,4 +1,84 @@
## Parity [v1.11.8](https://github.com/paritytech/parity-ethereum/releases/tag/v1.11.8) (2018-07-27)
Note: Parity 1.11 reached End-of-Life on 2018-09-19 (EOL).
## Parity-Ethereum [v1.11.11](https://github.com/paritytech/parity-ethereum/releases/tag/v1.11.11) (2018-09-11)
Parity-Ethereum 1.11.11-stable is a bug-fix release to improve performance and stability.
The full list of included changes:
- Stable backports 1.11.11 ([#9443](https://github.com/paritytech/parity-ethereum/pull/9443))
- Parity-version: bump stable to 1.11.11
- Update tobalaba.json ([#9419](https://github.com/paritytech/parity-ethereum/pull/9419))
- Update hardcoded sync ([#9421](https://github.com/paritytech/parity-ethereum/pull/9421))
- Update foundation hardcoded header to block 6219777
- Update ropsten hardcoded header to block 3917825
- Update kovan hardcoded header to block 8511489
- Parity: print correct keys path on startup ([#9501](https://github.com/paritytech/parity-ethereum/pull/9501))
- Only check warp syncing for eth_getWorks ([#9484](https://github.com/paritytech/parity-ethereum/pull/9484))
- Only check warp syncing for eth_getWorks
- Use SyncStatus::is_snapshot_syncing
## Parity-Ethereum [v1.11.10](https://github.com/paritytech/parity-ethereum/releases/tag/v1.11.10) (2018-08-31)
Parity-Ethereum 1.11.10-stable is a bug-fix release to improve performance and stability.
The full list of included changes:
- Stable backports for 1.11.10 ([#9228](https://github.com/paritytech/parity-ethereum/pull/9228))
- Parity-version: bump stable to 1.11.9
- Fix compilation error on nightly rust ([#8707](https://github.com/paritytech/parity-ethereum/pull/8707))
- On nightly rust passing `public_url` works but that breaks on stable. This works for both.
- Parity-version: bump stable to 1.11.10
- Check if synced when using eth_getWork ([#9193](https://github.com/paritytech/parity-ethereum/issues/9193)) ([#9210](https://github.com/paritytech/parity-ethereum/pull/9210))
- Check if synced when using eth_getWork ([#9193](https://github.com/paritytech/parity-ethereum/issues/9193))
- Don't use fn syncing
- Fix identation
- Fix typo
- Don't check for warping
- Rpc: avoid calling queue_info twice on eth_getWork
- Fix potential as_usize overflow when casting from U256 in miner ([#9221](https://github.com/paritytech/parity-ethereum/pull/9221))
- Allow old blocks from peers with lower difficulty ([#9226](https://github.com/paritytech/parity-ethereum/pull/9226))
- Previously we only allow downloading of old blocks if the peer difficulty was greater than our syncing difficulty. This change allows downloading of blocks from peers where the difficulty is greater then the last downloaded old block.
- Update Dockerfile ([#9242](https://github.com/paritytech/parity-ethereum/pull/9242))
- Update Dockerfile
- Fix Docker build
- Fix dockerfile paths: parity -> parity-ethereum ([#9248](https://github.com/paritytech/parity-ethereum/pull/9248))
- Update tobalaba.json ([#9313](https://github.com/paritytech/parity-ethereum/pull/9313))
- Light client `Provide default nonce in transactions when it´s missing` ([#9370](https://github.com/paritytech/parity-ethereum/pull/9370))
- Provide `default_nonce` in tx`s when it´s missing
- When `nonce` is missing in a `EthTransaction` will cause it to fall in these cases provide `default_nonce` value instead!
- Changed http:// to https:// on Yasm link ([#9369](https://github.com/paritytech/parity-ethereum/pull/9369))
- Changed http:// to https:// on Yasm link in README.md
- Provide `default_nonce` in tx`s when it´s missing
- When `nonce` is missing in a `EthTransaction` will cause it to fall in these cases provide `default_nonce` value instead!
- Address grumbles
- Ethcore: kovan: delay activation of strict score validation ([#9406](https://github.com/paritytech/parity-ethereum/pull/9406))
- Use impl Future in the light client RPC helpers ([#8628](https://github.com/paritytech/parity-ethereum/pull/8628))
- Better support for eth_getLogs in light mode ([#9186](https://github.com/paritytech/parity-ethereum/pull/9186))
- Light client on-demand request for headers range.
- Cache headers in HeaderWithAncestors response.
- Also fulfills request locally if all headers are in cache.
- Lightfetch::logs fetches missing headers on demand.
- Lightfetch::logs limit the number of headers requested at a time.
- Lightfetch::logs refactor header fetching logic.
- Enforce limit on header range length in light client logs request.
- Fix light request tests after struct change.
- Respond to review comments.
- Propagate transactions for next 4 blocks. ([#9265](https://github.com/paritytech/parity-ethereum/pull/9265))
- This PR also removes the limit of max 64 transactions per packet, currently we only attempt to prevent the packet size to go over 8MB. This will only be the case for super-large transactions or high-block-gas-limit chains.
- Patching this is important only for chains that have blocks that can fit more than 4k transactions (over 86M block gas limit)
- For mainnet, we should actually see a tiny bit faster propagation since instead of computing 4k pending set, we only need `4 * 8M / 21k = 1523` transactions.
- Ethcore: fix pow difficulty validation ([#9328](https://github.com/paritytech/parity-ethereum/pull/9328))
- Ethcore: fix pow difficulty validation
- Ethcore: validate difficulty is not zero
- Ethcore: add issue link to regression test
- Ethcore: fix tests
- Ethcore: move difficulty_to_boundary to ethash crate
- Ethcore: reuse difficulty_to_boundary and boundary_to_difficulty
- Ethcore: fix grumbles in difficulty_to_boundary_aux
- Add snapcraft cmake build dependency ([#9243](https://github.com/paritytech/parity-ethereum/pull/9243))
## Parity-Ethereum [v1.11.8](https://github.com/paritytech/parity-ethereum/releases/tag/v1.11.8) (2018-07-27)
Parity 1.11.8-stable is a bug-fix release to improve performance and stability.
@@ -42,7 +122,7 @@ The full list of included changes:
- Ethcore: update to parity-wasm 0.31
- Rpc: fix broken merge
## Parity [v1.11.7](https://github.com/paritytech/parity-ethereum/releases/tag/v1.11.7) "Prosperity" (2018-07-17)
## Parity-Ethereum [v1.11.7](https://github.com/paritytech/parity-ethereum/releases/tag/v1.11.7) "Prosperity" (2018-07-17)
Parity 1.11.7 "Prosperity" is a bug-fix release to improve performance and stability that marks the 1.11 release track as `stable`. Among other fixes, this release significantly addresses peering and synchronization issues. If you experienced such issues before, upgrading is highly recommended. If you rely on old versions of Parity, check out the `old-stable-1.10` branch, cherry-pick fixes, and compile your binaries independently. There will be no official support for any versions prior to 1.11.7, however (EOL).

618
docs/CHANGELOG-2.0.md Normal file
View File

@@ -0,0 +1,618 @@
## Parity-Ethereum [v2.0.8](https://github.com/paritytech/parity-ethereum/releases/tag/v2.0.8) (2018-10-16)
Parity-Ethereum 2.0.8-stable is a release that fixes a consensus issue with the recent Constantinople release. Upgrading is mandatory whatever network you are connected to that plans enabling EIP-1283, e.g., Ropsten, Kovan, Ethereum.
The full list of included changes:
- Stable release 2.0.8 backports ([#9748](https://github.com/paritytech/parity-ethereum/pull/9748))
- Parity-version: mark 2.0.8 stable as critical
- Use signed 256-bit integer for sstore gas refund substate ([#9746](https://github.com/paritytech/parity-ethereum/pull/9746))
- Add --force to cargo audit install script ([#9735](https://github.com/paritytech/parity-ethereum/pull/9735))
- Heads ref not present for branches beta and stable ([#9741](https://github.com/paritytech/parity-ethereum/pull/9741))
- Aura: fix panic on extra_info with unsealed block ([#9755](https://github.com/paritytech/parity-ethereum/pull/9755))
## Parity-Ethereum [v2.0.7](https://github.com/paritytech/parity-ethereum/releases/tag/v2.0.7) (2018-10-11)
Parity-Ethereum 2.0.7-stable is a release that introduces **Constantinople** to the Ethereum client. Upgrading is strongly recommended.
The following hardforks are supported by this release:
- Ropsten testnet block `4_230_000` on October 14, 2018 (Constantinople).
- POA core mainnet block `5_329_160` on October 22, 2018 (CORE HF 2).
- Kovan testnet block `9_200_000` on October 25, 2018 (Constantinople, KIP-{4,6}).
Running one of these networks, an upgrade to 2.0.7 or 2.1.2 is mandatory. More details can be found in Changelog below.
Please note, the following deprecations in our distribution of binaries:
- `arm*` targets are no longer served by parity, please consider (cross-)compiling from source yourself.
- `i*86` targets are no longer served by parity, please consider upgrading your operating system.
- Snapcraft is no longer maintained. please use binaries directly or your distro's repositories.
The full list of included changes:
- Stable Constantinople changes ([#9723](https://github.com/paritytech/parity-ethereum/pull/9723))
- Ethash: implement EIP-1234 ([#9187](https://github.com/paritytech/parity-ethereum/pull/9187))
- Implement EIP-1052 (EXTCODEHASH) and fix several issues in state account cache ([#9234](https://github.com/paritytech/parity-ethereum/pull/9234))
- Comply EIP-86 with the new definition ([#9140](https://github.com/paritytech/parity-ethereum/pull/9140))
- Implement KIP4: create2 for wasm ([#9277](https://github.com/paritytech/parity-ethereum/pull/9277))
- `gasleft` extern implemented for WASM runtime (kip-6) ([#9357](https://github.com/paritytech/parity-ethereum/pull/9357))
- Add EIP-1014 transition config flag ([#9268](https://github.com/paritytech/parity-ethereum/pull/9268))
- Eip 1283: Net gas metering for SSTORE without dirty maps ([#9319](https://github.com/paritytech/parity-ethereum/pull/9319))
- Update state tests execution model ([#9440](https://github.com/paritytech/parity-ethereum/pull/9440))
- Fix checkpointing when creating contract failed ([#9514](https://github.com/paritytech/parity-ethereum/pull/9514))
- In create memory calculation is the same for create2 because the additional parameter was popped before. ([#9522](https://github.com/paritytech/parity-ethereum/pull/9522))
- Enable all Constantinople hard fork changes in constantinople_test.json ([#9505](https://github.com/paritytech/parity-ethereum/pull/9505))
- Add constantinople conf to EvmTestClient. ([#9570](https://github.com/paritytech/parity-ethereum/pull/9570))
- Hardfork the testnets ([#9562](https://github.com/paritytech/parity-ethereum/pull/9562))
- Don't hash the init_code of CREATE. ([#9688](https://github.com/paritytech/parity-ethereum/pull/9688))
- Implement CREATE2 gas changes and fix some potential overflowing ([#9694](https://github.com/paritytech/parity-ethereum/pull/9694))
- Ethcore: delay ropsten hardfork ([#9704](https://github.com/paritytech/parity-ethereum/pull/9704))
- Add hardcoded headers ([#9730](https://github.com/paritytech/parity-ethereum/pull/9730))
- Gitlab ci: releasable_branches: change variables condition to schedule ([#9729](https://github.com/paritytech/parity-ethereum/pull/9729))
- Hf in POA Core (2018-10-22) ([#9724](https://github.com/paritytech/parity-ethereum/pull/9724))
- Backports for stable 2.0.7 ([#9648](https://github.com/paritytech/parity-ethereum/pull/9648))
- Parity-version: bump stable to 2.0.7
- Fix path to parity.h ([#9274](https://github.com/paritytech/parity-ethereum/pull/9274))
- Ethcore: fix detection of major import ([#9552](https://github.com/paritytech/parity-ethereum/pull/9552))
- Fix (light/provider) : Make `read_only executions` only read-only ([#9591](https://github.com/paritytech/parity-ethereum/pull/9591))
- Hf in POA Sokol (2018-09-19) ([#9607](https://github.com/paritytech/parity-ethereum/pull/9607))
- Fix failing node-table tests on mac os ([#9633](https://github.com/paritytech/parity-ethereum/pull/9633))
- Fix(light_fetch): avoid race with BlockNumber::Latest ([#9665](https://github.com/paritytech/parity-ethereum/pull/9665))
- Ci: Remove unnecessary pipes ([#9681](https://github.com/paritytech/parity-ethereum/pull/9681))
- Docker: run parity as normal user ([#9689](https://github.com/paritytech/parity-ethereum/pull/9689))
- Ci: Skip docs job for master and nightly ([#9693](https://github.com/paritytech/parity-ethereum/pull/9693))
- Ethcore-io retries failed work steal ([#9651](https://github.com/paritytech/parity-ethereum/pull/9651))
## Parity-Ethereum [v2.0.6](https://github.com/paritytech/parity-ethereum/releases/tag/v2.0.6) (2018-09-20)
Parity-Ethereum 2.0.6-stable is a release that does not improve performance and stability; no changes were made.
The full list of included changes:
- Backports to 2.0.6 stable ([#9600](https://github.com/paritytech/parity-ethereum/pull/9600))
- Ci: disable build cache for json-rpc-docs ([#9587](https://github.com/paritytech/parity-ethereum/pull/9587))
## Parity-Ethereum [v2.0.5](https://github.com/paritytech/parity-ethereum/releases/tag/v2.0.5) (2018-09-18)
Parity-Ethereum 2.0.5-stable is a bug-fix release to improve performance and stability.
Please, note:
- This release marks the 2.0 track of Parity-Ethereum as stable.
- This release contains a low-severity issue with the web-sockets ports. [#9545](https://github.com/paritytech/parity-ethereum/pull/9545)
- This release resolves a potential network fragmentation issue. [#9526](https://github.com/paritytech/parity-ethereum/pull/9526)
- The default `gas_floor_target` was increased to `8_000_000`, the default `gas_cap` to `10_000_000`.
- With this release, all versions of Parity Ethereum 1.x prior to 2.0 reached end of life.
- Users are urged to upgrade to 2.0.5-stable or 2.1.0-beta.
The full list of included changes:
- Backports for 2.0.5 stable ([#9519](https://github.com/paritytech/parity-ethereum/pull/9519))
- Parity-version: mark 2.0.5 track stable
- Deps: bump fs-swap to 0.2.4
- Remove initial token for WS. ([#9545](https://github.com/paritytech/parity-ethereum/pull/9545))
- Version: mark release critical
- Increase Gas-floor-target and Gas Cap ([#9564](https://github.com/paritytech/parity-ethereum/pull/9564))
- Gas-floor-target increased to 8M by default
- Gas-cap increased to 10M by default
- Improve P2P discovery ([#9526](https://github.com/paritytech/parity-ethereum/pull/9526))
- Add `target` to Rust traces
- Network-devp2p: Don't remove discovery peer in main sync
- Network-p2p: Refresh discovery more often
- Update Peer discovery protocol
- Run discovery more often when not enough nodes connected
- Start the first discovery early
- Update fast discovery rate
- Fix tests
- Fix `ping` tests
- Fixing remote Node address ; adding PingPong round
- Fix tests: update new +1 PingPong round
- Increase slow Discovery rate
- Check in flight FindNode before pings
- Add `deprecated` to deprecated_echo_hash
- Refactor `discovery_round` branching
- Net_version caches network_id to avoid redundant acquire of sync read lock ([#9544](https://github.com/paritytech/parity-ethereum/pull/9544))
- Net_version caches network_id to avoid redundant acquire of sync read lock, [#8746](https://github.com/paritytech/parity-ethereum/issues/8746)
- Use lower_hex display formatting for `net_peerCount` RPC method
- Update snapcraft.yaml ([#9530](https://github.com/paritytech/parity-ethereum/pull/9530))
- Fix DEPRECATED `prepare`
- Fix TODO https://bugs.launchpad.net/snapcraft/+bug/1778530
## Parity-Ethereum [v2.0.4](https://github.com/paritytech/parity-ethereum/releases/tag/v2.0.4) (2018-09-11)
Parity-Ethereum 2.0.4-beta is a bug-fix release to improve performance and stability:
- `eth_coinbase` now provides an actual account for light clients
- don't report skipped primaries when empty steps are enabled in proof-of-authority networks
- fix snapshot restoration failure on windows
- check warp sync status for `eth_getWorks`
The full list of included changes:
- Beta backports to 2.0.4 ([#9452](https://github.com/paritytech/parity-ethereum/pull/9452))
- Parity-version: bump beta to 2.0.4
- [Light/jsonrpc] Provide the actual account for `eth_coinbase` RPC and unify error handeling for light and full client ([#9383](https://github.com/paritytech/parity-ethereum/pull/9383))
- Provide the actual `account` for eth_coinbase
- The previous implementation always provided the `zero address` on `eth_coinbase` RPC. Now, instead the actual address is returned on success or an error when no account(s) is found!
- Full client `eth_coinbase` return err
- In the full-client return an error when no account is found instead of returning the `zero address`
- Remove needless blocks on single import
- Remove needless `static` lifetime on const
- Fix `rpc_eth_author` test
- Parity: print correct keys path on startup ([#9501](https://github.com/paritytech/parity-ethereum/pull/9501))
- Aura: don't report skipped primaries when empty steps are enabled ([#9435](https://github.com/paritytech/parity-ethereum/pull/9435))
- Only check warp syncing for eth_getWorks ([#9484](https://github.com/paritytech/parity-ethereum/pull/9484))
- Only check warp syncing for eth_getWorks
- Use SyncStatus::is_snapshot_syncing
- Fix Snapshot restoration failure on Windows ([#9491](https://github.com/paritytech/parity-ethereum/pull/9491))
- Close Blooms DB files before DB restoration
- Address Grumbles
## Parity-Ethereum [v2.0.3](https://github.com/paritytech/parity-ethereum/releases/tag/v2.0.3) (2018-09-01)
Parity-Ethereum 2.0.3-beta is a bug-fix release to improve performance and stability. Hopefully. ;)
The full list of included changes:
- Beta backports for 2.0.3 ([#9229](https://github.com/paritytech/parity-ethereum/pull/9229))
- parity-version: bump beta to 2.0.2
- remove ssl from dockerfiles, closes [#8880](https://github.com/paritytech/parity-ethereum/issues/8880) ([#9195](https://github.com/paritytech/parity-ethereum/pull/9195))
- snap: remove ssl dependencies from snapcraft definition ([#9222](https://github.com/paritytech/parity-ethereum/pull/9222))
- parity-version: bump beta to 2.0.3
- Remove all dapp permissions related settings ([#9120](https://github.com/paritytech/parity-ethereum/pull/9120))
- Completely remove all dapps struct from rpc
- Remove unused pub use
- Remove dapp policy/permission func in ethcore
- Remove all dapps settings from rpc
- Fix rpc tests
- Use both origin and user_agent
- Address grumbles
- Address grumbles
- Fix tests
- Check if synced when using eth_getWork ([#9193](https://github.com/paritytech/parity-ethereum/issues/9193)) ([#9210](https://github.com/paritytech/parity-ethereum/pull/9210))
- Check if synced when using eth_getWork ([#9193](https://github.com/paritytech/parity-ethereum/issues/9193))
- Don't use fn syncing
- Fix identation
- Fix typo
- Don't check for warping
- rpc: avoid calling queue_info twice on eth_getWork
- Fix potential as_usize overflow when casting from U256 in miner ([#9221](https://github.com/paritytech/parity-ethereum/pull/9221))
- Allow old blocks from peers with lower difficulty ([#9226](https://github.com/paritytech/parity-ethereum/pull/9226))
- Previously we only allow downloading of old blocks if the peer difficulty was greater than our syncing difficulty. This change allows downloading of blocks from peers where the difficulty is greater then the last downloaded old block.
- Update Dockerfile ([#9242](https://github.com/paritytech/parity-ethereum/pull/9242))
- Update Dockerfile
- fix Docker build
- fix dockerfile paths: parity -> parity-ethereum ([#9248](https://github.com/paritytech/parity-ethereum/pull/9248))
- Propagate transactions for next 4 blocks. ([#9265](https://github.com/paritytech/parity-ethereum/pull/9265))
- Closes [#9255](https://github.com/paritytech/parity-ethereum/issues/9255)
- This PR also removes the limit of max 64 transactions per packet, currently we only attempt to prevent the packet size to go over 8MB. This will only be the case for super-large transactions or high-block-gas-limit chains.
- Patching this is important only for chains that have blocks that can fit more than 4k transactions (over 86M block gas limit)
- For mainnet, we should actually see a tiny bit faster propagation since instead of computing 4k pending set, we only need `4 * 8M / 21k = 1523` transactions.
- Update tobalaba.json ([#9313](https://github.com/paritytech/parity-ethereum/pull/9313))
- Fix load share ([#9321](https://github.com/paritytech/parity-ethereum/pull/9321))
- fix(light_sync): calculate `load_share` properly
- refactor(api.rs): extract `light_params` fn, add test
- style(api.rs): add trailing commas
- ethcore: fix pow difficulty validation ([#9328](https://github.com/paritytech/parity-ethereum/pull/9328))
- ethcore: fix pow difficulty validation
- ethcore: validate difficulty is not zero
- ethcore: add issue link to regression test
- ethcore: fix tests
- ethcore: move difficulty_to_boundary to ethash crate
- ethcore: reuse difficulty_to_boundary and boundary_to_difficulty
- ethcore: fix grumbles in difficulty_to_boundary_aux
- Light client `Provide default nonce in transactions when it´s missing` ([#9370](https://github.com/paritytech/parity-ethereum/pull/9370))
- Provide `default_nonce` in tx's when it's missing
- When `nonce` is missing in a `EthTransaction` will cause it to fall in these cases provide `default_nonce` value instead!
- Changed http:// to https:// on Yasm link ([#9369](https://github.com/paritytech/parity-ethereum/pull/9369))
- Changed http:// to https:// on Yasm link in README.md
- Address grumbles
- ethcore: kovan: delay activation of strict score validation ([#9406](https://github.com/paritytech/parity-ethereum/pull/9406))
- Better support for eth_getLogs in light mode ([#9186](https://github.com/paritytech/parity-ethereum/pull/9186))
- Light client on-demand request for headers range.
- Cache headers in HeaderWithAncestors response.
- Also fulfills request locally if all headers are in cache.
- LightFetch::logs fetches missing headers on demand.
- LightFetch::logs limit the number of headers requested at a time.
- LightFetch::logs refactor header fetching logic.
- Enforce limit on header range length in light client logs request.
- Fix light request tests after struct change.
- Respond to review comments.
- Add update docs script to CI ([#9219](https://github.com/paritytech/parity-ethereum/pull/9219))
- Add update docs script to CI
- Added a script to CI that will use the jsonrpc tool to update rpc documentation then commit and push those to the wiki repo.
- fix gitlab ci lint
- Only apply jsonrpc docs update on tags
- Update gitlab-rpc-docs.sh
- Copy correct parity repo to jsonrpc folder
- Copy correct parity repo to jsonrpc folder before attempting to build docs since the CI runner clones the repo as parity and not parity-ethereum.
- Fix JSONRPC docs CI job
- Update remote config in wiki repo before pushing changes using a github token for authentication. Add message to wiki tag when pushing changes. Use project directory to correctly copy parity code base into the jsonrpc repo for doc generation.
- Fix set_remote_wiki function call in CI
- Prevent blockchain & miner racing when accessing pending block. ([#9310](https://github.com/paritytech/parity-ethereum/pull/9310))
- Prevent blockchain & miner racing when accessing pending block.
- Fix unavailability of pending block during reseal.
- Prevent sync restart if import queue full ([#9381](https://github.com/paritytech/parity-ethereum/pull/9381))
- Add POA Networks: Core and Sokol ([#9413](https://github.com/paritytech/parity-ethereum/pull/9413))
- ethcore: add poa network and sokol chainspecs
- rpc: simplify chain spec docs
- cli: rearrange networks by main/test and size/range
- parity: don't blacklist 0x00a328 on sokol testnet
- parity: add sokol and poanet to params and clean up a bit, add tests
- ethcore: add the poa networks and clean up a bit
- ethcore: fix path to poacore chain spec
- parity: rename poa networks to poacore and poasokol
- parity: fix configuration tests
- parity: fix parameter tests
- ethcore: rename POA Core and POA Sokol
- Update tobalaba.json ([#9419](https://github.com/paritytech/parity-ethereum/pull/9419))
- Update hardcoded sync ([#9421](https://github.com/paritytech/parity-ethereum/pull/9421))
- Update foundation hardcoded header to block 6219777
- Update ropsten hardcoded header to block 3917825
- Update kovan hardcoded header to block 8511489
## Parity-Ethereum [v2.0.1](https://github.com/paritytech/parity-ethereum/releases/tag/v2.0.1) (2018-07-27)
Parity-Ethereum 2.0.1-beta is a bug-fix release to improve performance and stability.
Note, authorities in PoA networks based on the Aura engine, should upgrade their nodes to 1.11.8-stable or 2.0.1-beta as this release includes a critical fix.
The full list of included changes:
- Backports to 2.0.1-beta ([#9145](https://github.com/paritytech/parity-ethereum/pull/9145))
- Parity-version: bump beta to 2.0.1
- Ci: update version strings for snaps ([#9160](https://github.com/paritytech/parity-ethereum/pull/9160))
- Be more graceful on Aura difficulty validation ([#9164](https://github.com/paritytech/parity-ethereum/pull/9164))
- Be more graceful on Aura difficulty validation
- Test: rejects_step_backwards
- Test: proposer_switching
- Test: rejects_future_block
- Test: reports_skipped
- Test: verify_empty_seal_steps
- Remove node-health ([#9119](https://github.com/paritytech/parity-ethereum/pull/9119))
- Remove node-health
- Remove ntp_servers
- Add --ntp-servers as legacy instead of removing it
- Add --ntp-servers to deprecated args
- Remove unused stuff
- Remove _legacy_ntp_servers
- Parity: fix UserDefaults json parser ([#9189](https://github.com/paritytech/parity-ethereum/pull/9189))
- Parity: fix UserDefaults json parser
- Parity: use serde_derive for UserDefaults
- Parity: support deserialization of old UserDefault json format
- Parity: make UserDefaults serde backwards compatible
- Parity: tabify indentation in UserDefaults
- Fix bugfix hard fork logic ([#9138](https://github.com/paritytech/parity-ethereum/pull/9138))
- Fix bugfix hard fork logic
- Remove dustProtectionTransition from bugfix category
- Eip-168 is not enabled by default
- Remove unnecessary 'static
- Disable per-sender limit for local transactions. ([#9148](https://github.com/paritytech/parity-ethereum/pull/9148))
- Disable per-sender limit for local transactions.
- Add a missing new line.
- Rpc: fix is_major_importing sync state condition ([#9112](https://github.com/paritytech/parity-ethereum/pull/9112))
- Rpc: fix is_major_importing sync state condition
- Rpc: fix informant printout when waiting for peers
- Fix verification in ethcore-sync collect_blocks ([#9135](https://github.com/paritytech/parity-ethereum/pull/9135))
- Docker: update hub dockerfile ([#9173](https://github.com/paritytech/parity-ethereum/pull/9173))
- Update Dockerfile for hub
- Update to Ubuntu Xenial 16.04
- Fix cmake version
- Docker: fix tab indentation in hub dockerfile
- Rpc: fix broken merge
- Rpc: remove node_health leftover from merge
- Rpc: remove dapps leftover from merge
## Parity-Ethereum [v2.0.0](https://github.com/paritytech/parity-ethereum/releases/tag/v2.0.0) "Ethereum" (2018-07-18)
This is the Parity-Ethereum//v2.0.0-beta release, code-named "Ethereum", **YOLO!**
Please note, Parity-Ethereum//v2.0.0 comes with some breaking changes that might be interrupting your usual workflows. Please mind them before upgrading:
- The Parity client is now called _Parity-Ethereum_ to distinguish it from other software we provide, such as [_Parity-Bitcoin_](https://github.com/paritytech/parity-bitcoin/) and [_Parity-Polkadot_](https://github.com/paritytech/polkadot) ([#9052](https://github.com/paritytech/parity-ethereum/pull/9052)).
- The public node and the user interface (a.k.a. _"Parity Wallet"_) are completely removed from the Parity-Ethereum//v2.0.0 client ([#8758](https://github.com/paritytech/parity-ethereum/pull/8758), [#8783](https://github.com/paritytech/parity-ethereum/pull/8783), [#8641](https://github.com/paritytech/parity-ethereum/pull/8641)). Users interested running a Parity Wallet, check out [the stand-alone UI application](https://github.com/Parity-JS/shell/releases).
- The DApps subsystem was completely removed from the client ([#9017](https://github.com/paritytech/parity-ethereum/pull/9017), [#9107](https://github.com/paritytech/parity-ethereum/pull/9107)). Again, use the standalone wallet if you wish to continue working with them.
- Windows and MacOS versions are not available as installer anymore and the system trays were removed ([#8778](https://github.com/paritytech/parity-ethereum/pull/8778)). If you desire to run Parity-Ethereum on Windows or MacOS, you still can get the binaries from our mirrors. Furthermore, MacOS users are encouraged [to use our homebrew tap](https://github.com/paritytech/homebrew-paritytech/).
- Linux versions are not available as deb-/rpm-packages anymore ([#8887](https://github.com/paritytech/parity-ethereum/pull/8887)). Communities are encouraged to provide their own packages or maintain their own repositories, such as [Arch Linux does](https://www.archlinux.org/packages/community/x86_64/parity/) for instance.
- MD5-checksums are completely replaced by SHA256-checksums ([#8884](https://github.com/paritytech/parity-ethereum/pull/8884)). This is also reflected on our homepage by now.
- Deprecated, removed, or replaced CLI-options are hidden from client `--help` to further discourage their usage ([#8967](https://github.com/paritytech/parity-ethereum/pull/8967)).
Additional noteworthy changes to the client:
- Tracing of precompiled contracts when the transfer value is not zero ([#8486](https://github.com/paritytech/parity-ethereum/pull/8486))
- _Parity-Ethereum_ as a library now provides APIs for running full and light nodes and a C interface ([#8412](https://github.com/paritytech/parity-ethereum/pull/8412)). Shared crates are now available in [_Parity-Common_](https://github.com/paritytech/parity-common) ([#9083](https://github.com/paritytech/parity-ethereum/pull/9083)).
- The Morden database and keys are now moved to a `./Morden` subdirectory instead of `./test` which is by default used by Ropsten ([#8621](https://github.com/paritytech/parity-ethereum/pull/8621)).
- Adding support for having an on-chain contract calculating the block rewards ([#8419](https://github.com/paritytech/parity-ethereum/pull/8419)).
- Enforcing warp-only synchronization with `--warp-barrier [blocknumber]` flag ([#8228](https://github.com/paritytech/parity-ethereum/pull/8228)).
- Adding a fork-choice and meta-data framework suitable for implementing Casper ([#8401](https://github.com/paritytech/parity-ethereum/pull/8401)).
- Returning an error if RLP-size of a transaction exceeds a 300kB limit ([#8473](https://github.com/paritytech/parity-ethereum/pull/8473)).
- Warp-sync is now resumable by keeping the downloaded chunks between client restarts. Also, it seeds downloaded snapshots for other nodes ([#8544](https://github.com/paritytech/parity-ethereum/pull/8544)).
- The developer chain `--chain dev` now contains Byzantium features, this breaks existing developer chains ([#8717](https://github.com/paritytech/parity-ethereum/pull/8717)).
- The EIP150, EIP160 and EIP161 forks are now to be specified in common params section of a chain-spec file instead of the Ethash params to enable these features on non-proof-of-work chains ([#8614](https://github.com/paritytech/parity-ethereum/pull/8614)). Please update your chain specs.
- Allowing to disable local-by-default for transactions with new configurations ([#8882](https://github.com/paritytech/parity-ethereum/pull/8882)).
- Never drop local transactions from different senders ([#9002](https://github.com/paritytech/parity-ethereum/pull/9002)).
- Optimize pending transactions filter and fix ethstats reporting of pending transactions ([#9026](https://github.com/paritytech/parity-ethereum/pull/9026)).
- Add separate database directory for light client allowing to run full and light nodes at the same time ([#9064](https://github.com/paritytech/parity-ethereum/pull/9064)).
If you are upgrading directly from versions 1.10.9 or earlier, please note important changes to our transaction-queue implementation, namely:
- The pool now limits transactions per-sender (see `--tx-queue-per-sender`), local transactions also have to obey that limit. Consider increasing the limit via CLI-flag when running benchmarks or sending a lot of transactions at once.
- In case the pool is full, transactions received over the network, but originating from accounts that you have private keys for might not get accepted to the pool any more with higher priority. Consider running with larger pool size or submitting the transactions directly on the node via `eth_sendRawTransaction`.
The full list of included changes:
- Backports to 2.0.0-beta ([#9094](https://github.com/paritytech/parity-ethereum/pull/9094))
- Parity-version: betalize 2.0
- Multiple improvements to discovery ping handling ([#8771](https://github.com/paritytech/parity-ethereum/pull/8771))
- Discovery: Only add nodes to routing table after receiving pong.
- Discovery: Refactor packet creation into its own function.
- Discovery: Additional testing for new add_node behavior.
- Discovery: Track expiration of pings to non-yet-in-bucket nodes.
- Discovery: Verify echo hash on pong packets.
- Discovery: Track timeouts on FIND_NODE requests.
- Discovery: Retry failed pings with exponential backoff.
- !fixup Use slice instead of Vec for request_backoff.
- Add separate database directory for light client ([#9064](https://github.com/paritytech/parity-ethereum/pull/9064))
- Add separate default DB path for light client ([#8927](https://github.com/paritytech/parity-ethereum/pull/8927))
- Improve readability
- Revert "Replace `std::env::home_dir` with `dirs::home_dir` ([#9077](https://github.com/paritytech/parity-ethereum/pull/9077))" ([#9097](https://github.com/paritytech/parity-ethereum/pull/9097))
- Revert "Replace `std::env::home_dir` with `dirs::home_dir` ([#9077](https://github.com/paritytech/parity-ethereum/pull/9077))"
- This reverts commit 7e77932.
- Restore some of the changes
- Update parity-common
- Offload cull to IoWorker. ([#9099](https://github.com/paritytech/parity-ethereum/pull/9099))
- Fix work-notify. ([#9104](https://github.com/paritytech/parity-ethereum/pull/9104))
- Update hidapi, fixes [#7542](https://github.com/paritytech/parity-ethereum/issues/7542) ([#9108](https://github.com/paritytech/parity-ethereum/pull/9108))
- Docker: add cmake dependency ([#9111](https://github.com/paritytech/parity-ethereum/pull/9111))
- Update light client hardcoded headers ([#9098](https://github.com/paritytech/parity-ethereum/pull/9098))
- Insert Kovan hardcoded headers until 7690241
- Insert Kovan hardcoded headers until block 7690241
- Insert Ropsten hardcoded headers until 3612673
- Insert Mainnet hardcoded headers until block 5941249
- Make sure to produce full blocks. ([#9115](https://github.com/paritytech/parity-ethereum/pull/9115))
- Insert ETC (classic) hardcoded headers until block 6170625 ([#9121](https://github.com/paritytech/parity-ethereum/pull/9121))
- Fix verification in ethcore-sync collect_blocks ([#9135](https://github.com/paritytech/parity-ethereum/pull/9135))
- Completely remove all dapps struct from rpc ([#9107](https://github.com/paritytech/parity-ethereum/pull/9107))
- Completely remove all dapps struct from rpc
- Remove unused pub use
- `evm bench` fix broken dependencies ([#9134](https://github.com/paritytech/parity-ethereum/pull/9134))
- `evm bench` use valid dependencies
- Benchmarks of the `evm` used stale versions of a couple a crates that this commit fixes!
- Fix warnings
- Update snapcraft.yaml ([#9132](https://github.com/paritytech/parity-ethereum/pull/9132))
- Parity Ethereum 2.0.0 ([#9052](https://github.com/paritytech/parity-ethereum/pull/9052))
- Don't fetch snapshot chunks at random ([#9088](https://github.com/paritytech/parity-ethereum/pull/9088))
- Remove the dapps system ([#9017](https://github.com/paritytech/parity-ethereum/pull/9017))
- Fix nightly warnings ([#9080](https://github.com/paritytech/parity-ethereum/pull/9080))
- Db: remove wal disabling / fast-and-loose option. ([#8963](https://github.com/paritytech/parity-ethereum/pull/8963))
- Transactions hashes missing in trace_replayBlockTransactions method result [#8725](https://github.com/paritytech/parity-ethereum/issues/8725) ([#8883](https://github.com/paritytech/parity-ethereum/pull/8883))
- Delete crates from parity-ethereum and fetch them from parity-common instead ([#9083](https://github.com/paritytech/parity-ethereum/pull/9083))
- Updater verification ([#8787](https://github.com/paritytech/parity-ethereum/pull/8787))
- Phrasing, precisions and typos in CLI help ([#9060](https://github.com/paritytech/parity-ethereum/pull/9060))
- Some work towards iOS build ([#9045](https://github.com/paritytech/parity-ethereum/pull/9045))
- Clean up deprecated options and add CHECK macro ([#9036](https://github.com/paritytech/parity-ethereum/pull/9036))
- Replace `std::env::home_dir` with `dirs::home_dir` ([#9077](https://github.com/paritytech/parity-ethereum/pull/9077))
- Fix warning in secret-store test ([#9074](https://github.com/paritytech/parity-ethereum/pull/9074))
- Seedhashcompute remove needless `new` impl ([#9063](https://github.com/paritytech/parity-ethereum/pull/9063))
- Remove trait bounds from several structs ([#9055](https://github.com/paritytech/parity-ethereum/pull/9055))
- Docs: add changelog for 1.10.9 stable and 1.11.6 beta ([#9069](https://github.com/paritytech/parity-ethereum/pull/9069))
- Enable test in `miner/pool/test` ([#9072](https://github.com/paritytech/parity-ethereum/pull/9072))
- Fetch: replace futures-timer with tokio-timer ([#9066](https://github.com/paritytech/parity-ethereum/pull/9066))
- Remove util-error ([#9054](https://github.com/paritytech/parity-ethereum/pull/9054))
- Fixes for misbehavior reporting in AuthorityRound ([#8998](https://github.com/paritytech/parity-ethereum/pull/8998))
- A last bunch of txqueue performance optimizations ([#9024](https://github.com/paritytech/parity-ethereum/pull/9024))
- Reduce number of constraints for triedb types ([#9043](https://github.com/paritytech/parity-ethereum/pull/9043))
- Bump fs-swap to 0.2.3 so it is compatible with osx 10.11 again ([#9050](https://github.com/paritytech/parity-ethereum/pull/9050))
- Recursive test ([#9042](https://github.com/paritytech/parity-ethereum/pull/9042))
- Introduce more optional features in ethcore ([#9020](https://github.com/paritytech/parity-ethereum/pull/9020))
- Update ETSC bootnodes ([#9038](https://github.com/paritytech/parity-ethereum/pull/9038))
- Optimize pending transactions filter ([#9026](https://github.com/paritytech/parity-ethereum/pull/9026))
- Eip160/eip161 spec: u64 -> BlockNumber ([#9044](https://github.com/paritytech/parity-ethereum/pull/9044))
- Move the C/C++ example to another directory ([#9032](https://github.com/paritytech/parity-ethereum/pull/9032))
- Bump parking_lot to 0.6 ([#9013](https://github.com/paritytech/parity-ethereum/pull/9013))
- Never drop local transactions from different senders. ([#9002](https://github.com/paritytech/parity-ethereum/pull/9002))
- Precise HTTP or WebSockets for JSON-RPC options ([#9027](https://github.com/paritytech/parity-ethereum/pull/9027))
- Recently rejected cache for transaction queue ([#9005](https://github.com/paritytech/parity-ethereum/pull/9005))
- Make HashDB generic ([#8739](https://github.com/paritytech/parity-ethereum/pull/8739))
- Only return error log for rustls ([#9025](https://github.com/paritytech/parity-ethereum/pull/9025))
- Update Changelogs for 1.10.8 and 1.11.5 ([#9012](https://github.com/paritytech/parity-ethereum/pull/9012))
- Attempt to graceful shutdown in case of panics ([#8999](https://github.com/paritytech/parity-ethereum/pull/8999))
- Simplify kvdb error types ([#8924](https://github.com/paritytech/parity-ethereum/pull/8924))
- Add option for user to set max size limit for RPC requests ([#9010](https://github.com/paritytech/parity-ethereum/pull/9010))
- Bump ntp to 0.5.0 ([#9009](https://github.com/paritytech/parity-ethereum/pull/9009))
- Removed duplicate dependency ([#9021](https://github.com/paritytech/parity-ethereum/pull/9021))
- Minimal effective gas price in the queue ([#8934](https://github.com/paritytech/parity-ethereum/pull/8934))
- Parity: fix db path when migrating to blooms db ([#8975](https://github.com/paritytech/parity-ethereum/pull/8975))
- Preserve the current abort behavior ([#8995](https://github.com/paritytech/parity-ethereum/pull/8995))
- Improve should_replace on NonceAndGasPrice ([#8980](https://github.com/paritytech/parity-ethereum/pull/8980))
- Tentative fix for missing dependency error ([#8973](https://github.com/paritytech/parity-ethereum/pull/8973))
- Refactor evm Instruction to be a c-like enum ([#8914](https://github.com/paritytech/parity-ethereum/pull/8914))
- Fix deadlock in blockchain. ([#8977](https://github.com/paritytech/parity-ethereum/pull/8977))
- Snap: downgrade rust to revision 1.26.2, ref snapcraft/+bug/1778530 ([#8984](https://github.com/paritytech/parity-ethereum/pull/8984))
- Use local parity-dapps-glue instead of crate published at crates.io ([#8983](https://github.com/paritytech/parity-ethereum/pull/8983))
- Parity: omit redundant last imported block number in light sync informant ([#8962](https://github.com/paritytech/parity-ethereum/pull/8962))
- Disable hardware-wallets on platforms that don't support `libusb` ([#8464](https://github.com/paritytech/parity-ethereum/pull/8464))
- Bump error-chain and quick_error versions ([#8972](https://github.com/paritytech/parity-ethereum/pull/8972))
- Evm benchmark utilities ([#8944](https://github.com/paritytech/parity-ethereum/pull/8944))
- Parity: hide legacy options from cli --help ([#8967](https://github.com/paritytech/parity-ethereum/pull/8967))
- Scripts: fix docker build tag on latest using master ([#8952](https://github.com/paritytech/parity-ethereum/pull/8952))
- Add type for passwords. ([#8920](https://github.com/paritytech/parity-ethereum/pull/8920))
- Deps: bump fs-swap ([#8953](https://github.com/paritytech/parity-ethereum/pull/8953))
- Eliminate some more `transmute()` ([#8879](https://github.com/paritytech/parity-ethereum/pull/8879))
- Restrict vault.json permssion to owner and using random suffix for temp vault.json file ([#8932](https://github.com/paritytech/parity-ethereum/pull/8932))
- Print SS.self_public when starting SS node ([#8949](https://github.com/paritytech/parity-ethereum/pull/8949))
- Scripts: minor improvements ([#8930](https://github.com/paritytech/parity-ethereum/pull/8930))
- Rpc: cap gas limit of local calls ([#8943](https://github.com/paritytech/parity-ethereum/pull/8943))
- Docs: update changelogs ([#8931](https://github.com/paritytech/parity-ethereum/pull/8931))
- Ethcore: fix compilation when using slow-blocks or evm-debug features ([#8936](https://github.com/paritytech/parity-ethereum/pull/8936))
- Fixed blooms dir creation ([#8941](https://github.com/paritytech/parity-ethereum/pull/8941))
- Update hardcoded headers ([#8925](https://github.com/paritytech/parity-ethereum/pull/8925))
- New blooms database ([#8712](https://github.com/paritytech/parity-ethereum/pull/8712))
- Ethstore: retry deduplication of wallet file names until success ([#8910](https://github.com/paritytech/parity-ethereum/pull/8910))
- Update ropsten.json ([#8926](https://github.com/paritytech/parity-ethereum/pull/8926))
- Include node identity in the P2P advertised client version. ([#8830](https://github.com/paritytech/parity-ethereum/pull/8830))
- Allow disabling local-by-default for transactions with new config entry ([#8882](https://github.com/paritytech/parity-ethereum/pull/8882))
- Allow Poll Lifetime to be configured via CLI ([#8885](https://github.com/paritytech/parity-ethereum/pull/8885))
- Cleanup nibbleslice ([#8915](https://github.com/paritytech/parity-ethereum/pull/8915))
- Hardware-wallets `Clean up things I missed in the latest PR` ([#8890](https://github.com/paritytech/parity-ethereum/pull/8890))
- Remove debian/.deb and centos/.rpm packaging scripts ([#8887](https://github.com/paritytech/parity-ethereum/pull/8887))
- Remove a weird emoji in new_social docs ([#8913](https://github.com/paritytech/parity-ethereum/pull/8913))
- Minor fix in chain supplier and light provider ([#8906](https://github.com/paritytech/parity-ethereum/pull/8906))
- Block 0 is valid in queries ([#8891](https://github.com/paritytech/parity-ethereum/pull/8891))
- Fixed osx permissions ([#8901](https://github.com/paritytech/parity-ethereum/pull/8901))
- Atomic create new files with permissions to owner in ethstore ([#8896](https://github.com/paritytech/parity-ethereum/pull/8896))
- Add ETC Cooperative-run load balanced parity node ([#8892](https://github.com/paritytech/parity-ethereum/pull/8892))
- Add support for --chain tobalaba ([#8870](https://github.com/paritytech/parity-ethereum/pull/8870))
- Fix some warns on nightly ([#8889](https://github.com/paritytech/parity-ethereum/pull/8889))
- Add new ovh bootnodes and fix port for foundation bootnode 3.2 ([#8886](https://github.com/paritytech/parity-ethereum/pull/8886))
- Secretstore: service pack 1 ([#8435](https://github.com/paritytech/parity-ethereum/pull/8435))
- Handle removed logs in filter changes and add geth compatibility field ([#8796](https://github.com/paritytech/parity-ethereum/pull/8796))
- Fixed ipc leak, closes [#8774](https://github.com/paritytech/parity-ethereum/issues/8774) ([#8876](https://github.com/paritytech/parity-ethereum/pull/8876))
- Scripts: remove md5 checksums ([#8884](https://github.com/paritytech/parity-ethereum/pull/8884))
- Hardware_wallet/Ledger `Sign messages` + some refactoring ([#8868](https://github.com/paritytech/parity-ethereum/pull/8868))
- Check whether we need resealing in miner and unwrap has_account in account_provider ([#8853](https://github.com/paritytech/parity-ethereum/pull/8853))
- Docker: Fix alpine build ([#8878](https://github.com/paritytech/parity-ethereum/pull/8878))
- Remove mac os installers etc ([#8875](https://github.com/paritytech/parity-ethereum/pull/8875))
- Readme.md: update the list of dependencies ([#8864](https://github.com/paritytech/parity-ethereum/pull/8864))
- Fix concurrent access to signer queue ([#8854](https://github.com/paritytech/parity-ethereum/pull/8854))
- Tx permission contract improvement ([#8400](https://github.com/paritytech/parity-ethereum/pull/8400))
- Limit the number of transactions in pending set ([#8777](https://github.com/paritytech/parity-ethereum/pull/8777))
- Use sealing.enabled to emit eth_mining information ([#8844](https://github.com/paritytech/parity-ethereum/pull/8844))
- Don't allocate in expect_valid_rlp unless necessary ([#8867](https://github.com/paritytech/parity-ethereum/pull/8867))
- Fix Cli Return Code on --help for ethkey, ethstore & whisper ([#8863](https://github.com/paritytech/parity-ethereum/pull/8863))
- Fix subcrate test compile ([#8862](https://github.com/paritytech/parity-ethereum/pull/8862))
- Network-devp2p: downgrade logging to debug, add target ([#8784](https://github.com/paritytech/parity-ethereum/pull/8784))
- Clearing up a comment about the prefix for signing ([#8828](https://github.com/paritytech/parity-ethereum/pull/8828))
- Disable parallel verification and skip verifiying already imported txs. ([#8834](https://github.com/paritytech/parity-ethereum/pull/8834))
- Devp2p: Move UDP socket handling from Discovery to Host. ([#8790](https://github.com/paritytech/parity-ethereum/pull/8790))
- Fixed AuthorityRound deadlock on shutdown, closes [#8088](https://github.com/paritytech/parity-ethereum/issues/8088) ([#8803](https://github.com/paritytech/parity-ethereum/pull/8803))
- Specify critical release flag per network ([#8821](https://github.com/paritytech/parity-ethereum/pull/8821))
- Fix `deadlock_detection` feature branch compilation ([#8824](https://github.com/paritytech/parity-ethereum/pull/8824))
- Use system allocator when profiling memory ([#8831](https://github.com/paritytech/parity-ethereum/pull/8831))
- Added from and to to Receipt ([#8756](https://github.com/paritytech/parity-ethereum/pull/8756))
- Ethcore: fix ancient block error msg handling ([#8832](https://github.com/paritytech/parity-ethereum/pull/8832))
- Ci: Fix docker tags ([#8822](https://github.com/paritytech/parity-ethereum/pull/8822))
- Parity: fix indentation in sync logging ([#8794](https://github.com/paritytech/parity-ethereum/pull/8794))
- Removed obsolete IpcMode enum ([#8819](https://github.com/paritytech/parity-ethereum/pull/8819))
- Remove UI related settings from CLI ([#8783](https://github.com/paritytech/parity-ethereum/pull/8783))
- Remove windows tray and installer ([#8778](https://github.com/paritytech/parity-ethereum/pull/8778))
- Docs: add changelogs for 1.10.6 and 1.11.3 ([#8810](https://github.com/paritytech/parity-ethereum/pull/8810))
- Fix ancient blocks queue deadlock ([#8751](https://github.com/paritytech/parity-ethereum/pull/8751))
- Disallow unsigned transactions in case EIP-86 is disabled ([#8802](https://github.com/paritytech/parity-ethereum/pull/8802))
- Fix evmbin compilation ([#8795](https://github.com/paritytech/parity-ethereum/pull/8795))
- Have space between feature cfg flag ([#8791](https://github.com/paritytech/parity-ethereum/pull/8791))
- Rpc: fix address formatting in TransactionRequest Display ([#8786](https://github.com/paritytech/parity-ethereum/pull/8786))
- Conditionally compile ethcore public test helpers ([#8743](https://github.com/paritytech/parity-ethereum/pull/8743))
- Remove Result wrapper from AccountProvider in RPC impls ([#8763](https://github.com/paritytech/parity-ethereum/pull/8763))
- Update `license header` and `scripts` ([#8666](https://github.com/paritytech/parity-ethereum/pull/8666))
- Remove HostTrait altogether ([#8681](https://github.com/paritytech/parity-ethereum/pull/8681))
- Ethcore-sync: fix connection to peers behind chain fork block ([#8710](https://github.com/paritytech/parity-ethereum/pull/8710))
- Remove public node settings from cli ([#8758](https://github.com/paritytech/parity-ethereum/pull/8758))
- Custom Error Messages on ENFILE and EMFILE IO Errors ([#8744](https://github.com/paritytech/parity-ethereum/pull/8744))
- Ci: Fixes for Android Pipeline ([#8745](https://github.com/paritytech/parity-ethereum/pull/8745))
- Remove NetworkService::config() ([#8653](https://github.com/paritytech/parity-ethereum/pull/8653))
- Fix XOR distance calculation in discovery Kademlia impl ([#8589](https://github.com/paritytech/parity-ethereum/pull/8589))
- Print warnings when fetching pending blocks ([#8711](https://github.com/paritytech/parity-ethereum/pull/8711))
- Fix PoW blockchains sealing notifications in chain_new_blocks ([#8656](https://github.com/paritytech/parity-ethereum/pull/8656))
- Remove -k/--insecure option from curl installer ([#8719](https://github.com/paritytech/parity-ethereum/pull/8719))
- Ease tiny-keccak version requirements (1.4.1 -> 1.4) ([#8726](https://github.com/paritytech/parity-ethereum/pull/8726))
- Bump tinykeccak to 1.4 ([#8728](https://github.com/paritytech/parity-ethereum/pull/8728))
- Remove a couple of unnecessary `transmute()` ([#8736](https://github.com/paritytech/parity-ethereum/pull/8736))
- Fix some nits using clippy ([#8731](https://github.com/paritytech/parity-ethereum/pull/8731))
- Add 'interface' option to cli ([#8699](https://github.com/paritytech/parity-ethereum/pull/8699))
- Remove unused function new_pow_test_spec ([#8735](https://github.com/paritytech/parity-ethereum/pull/8735))
- Add a deadlock detection thread ([#8727](https://github.com/paritytech/parity-ethereum/pull/8727))
- Fix local transactions policy. ([#8691](https://github.com/paritytech/parity-ethereum/pull/8691))
- Shutdown the Snapshot Service early ([#8658](https://github.com/paritytech/parity-ethereum/pull/8658))
- Network-devp2p: handle UselessPeer disconnect ([#8686](https://github.com/paritytech/parity-ethereum/pull/8686))
- Fix compilation error on nightly rust ([#8707](https://github.com/paritytech/parity-ethereum/pull/8707))
- Add a test for decoding corrupt data ([#8713](https://github.com/paritytech/parity-ethereum/pull/8713))
- Update dev chain ([#8717](https://github.com/paritytech/parity-ethereum/pull/8717))
- Remove unused imports ([#8722](https://github.com/paritytech/parity-ethereum/pull/8722))
- Implement recursive Debug for Nodes in patrica_trie::TrieDB ([#8697](https://github.com/paritytech/parity-ethereum/pull/8697))
- Parity: trim whitespace when parsing duration strings ([#8692](https://github.com/paritytech/parity-ethereum/pull/8692))
- Set the request index to that of the current request ([#8683](https://github.com/paritytech/parity-ethereum/pull/8683))
- Remove empty file ([#8705](https://github.com/paritytech/parity-ethereum/pull/8705))
- Update mod.rs ([#8695](https://github.com/paritytech/parity-ethereum/pull/8695))
- Use impl Future in the light client RPC helpers ([#8628](https://github.com/paritytech/parity-ethereum/pull/8628))
- Fix cli signer ([#8682](https://github.com/paritytech/parity-ethereum/pull/8682))
- Allow making direct RPC queries from the C API ([#8588](https://github.com/paritytech/parity-ethereum/pull/8588))
- Remove the error when stopping the network ([#8671](https://github.com/paritytech/parity-ethereum/pull/8671))
- Move connection_filter to the network crate ([#8674](https://github.com/paritytech/parity-ethereum/pull/8674))
- Remove HostInfo::client_version() and secret() ([#8677](https://github.com/paritytech/parity-ethereum/pull/8677))
- Refactor EIP150, EIP160 and EIP161 forks to be specified in CommonParams ([#8614](https://github.com/paritytech/parity-ethereum/pull/8614))
- Parity: improve cli help and logging ([#8665](https://github.com/paritytech/parity-ethereum/pull/8665))
- Updated tiny-keccak to 1.4.2 ([#8669](https://github.com/paritytech/parity-ethereum/pull/8669))
- Remove the Keccak C library and use the pure Rust impl ([#8657](https://github.com/paritytech/parity-ethereum/pull/8657))
- Remove HostInfo::next_nonce ([#8644](https://github.com/paritytech/parity-ethereum/pull/8644))
- Fix not downloading old blocks ([#8642](https://github.com/paritytech/parity-ethereum/pull/8642))
- Resumable warp-sync / Seed downloaded snapshots ([#8544](https://github.com/paritytech/parity-ethereum/pull/8544))
- Don't open Browser post-install on Mac ([#8641](https://github.com/paritytech/parity-ethereum/pull/8641))
- Changelog for 1.10.4-stable and 1.11.1-beta ([#8637](https://github.com/paritytech/parity-ethereum/pull/8637))
- Typo ([#8640](https://github.com/paritytech/parity-ethereum/pull/8640))
- Fork choice and metadata framework for Engine ([#8401](https://github.com/paritytech/parity-ethereum/pull/8401))
- Check that the Android build doesn't dep on c++_shared ([#8538](https://github.com/paritytech/parity-ethereum/pull/8538))
- Remove NetworkContext::io_channel() ([#8625](https://github.com/paritytech/parity-ethereum/pull/8625))
- Fix light sync with initial validator-set contract ([#8528](https://github.com/paritytech/parity-ethereum/pull/8528))
- Store morden db and keys in "path/to/parity/data/Morden" (ropsten uses "test", like before) ([#8621](https://github.com/paritytech/parity-ethereum/pull/8621))
- ´main.rs´ typo ([#8629](https://github.com/paritytech/parity-ethereum/pull/8629))
- Fix BlockReward contract "arithmetic operation overflow" ([#8611](https://github.com/paritytech/parity-ethereum/pull/8611))
- Gitlab test script fixes ([#8573](https://github.com/paritytech/parity-ethereum/pull/8573))
- Remove manually added text to the errors ([#8595](https://github.com/paritytech/parity-ethereum/pull/8595))
- Fix account list double 0x display ([#8596](https://github.com/paritytech/parity-ethereum/pull/8596))
- Typo: wrong indentation in kovan config ([#8610](https://github.com/paritytech/parity-ethereum/pull/8610))
- Fix packet count when talking with PAR2 peers ([#8555](https://github.com/paritytech/parity-ethereum/pull/8555))
- Use full qualified syntax for itertools::Itertools::flatten ([#8606](https://github.com/paritytech/parity-ethereum/pull/8606))
- 2 tiny modification on snapshot ([#8601](https://github.com/paritytech/parity-ethereum/pull/8601))
- Fix the mio test again ([#8602](https://github.com/paritytech/parity-ethereum/pull/8602))
- Remove inject.js server-side injection for dapps ([#8539](https://github.com/paritytech/parity-ethereum/pull/8539))
- Block_header can fail so return Result ([#8581](https://github.com/paritytech/parity-ethereum/pull/8581))
- Block::decode() returns Result ([#8586](https://github.com/paritytech/parity-ethereum/pull/8586))
- Fix compiler warning ([#8590](https://github.com/paritytech/parity-ethereum/pull/8590))
- Fix Parity UI link ([#8600](https://github.com/paritytech/parity-ethereum/pull/8600))
- Make mio optional in ethcore-io ([#8537](https://github.com/paritytech/parity-ethereum/pull/8537))
- Attempt to fix intermittent test failures ([#8584](https://github.com/paritytech/parity-ethereum/pull/8584))
- Changelog and Readme ([#8591](https://github.com/paritytech/parity-ethereum/pull/8591))
- Added Dockerfile for alpine linux by @andresilva, closes [#3565](https://github.com/paritytech/parity-ethereum/issues/3565) ([#8587](https://github.com/paritytech/parity-ethereum/pull/8587))
- Add whisper CLI to the pipelines ([#8578](https://github.com/paritytech/parity-ethereum/pull/8578))
- Rename `whisper-cli binary` to `whisper` ([#8579](https://github.com/paritytech/parity-ethereum/pull/8579))
- Changelog nit ([#8585](https://github.com/paritytech/parity-ethereum/pull/8585))
- Remove unnecessary cloning in overwrite_with ([#8580](https://github.com/paritytech/parity-ethereum/pull/8580))
- Handle socket address parsing errors ([#8545](https://github.com/paritytech/parity-ethereum/pull/8545))
- Update CHANGELOG for 1.9, 1.10, and 1.11 ([#8556](https://github.com/paritytech/parity-ethereum/pull/8556))
- Decoding headers can fail ([#8570](https://github.com/paritytech/parity-ethereum/pull/8570))
- Refactoring `ethcore-sync` - Fixing warp-sync barrier ([#8543](https://github.com/paritytech/parity-ethereum/pull/8543))
- Remove State::replace_backend ([#8569](https://github.com/paritytech/parity-ethereum/pull/8569))
- Make trace-time publishable. ([#8568](https://github.com/paritytech/parity-ethereum/pull/8568))
- Don't block sync when importing old blocks ([#8530](https://github.com/paritytech/parity-ethereum/pull/8530))
- Trace precompiled contracts when the transfer value is not zero ([#8486](https://github.com/paritytech/parity-ethereum/pull/8486))
- Parity as a library ([#8412](https://github.com/paritytech/parity-ethereum/pull/8412))
- Rlp decode returns Result ([#8527](https://github.com/paritytech/parity-ethereum/pull/8527))
- Node table sorting according to last contact data ([#8541](https://github.com/paritytech/parity-ethereum/pull/8541))
- Keep all enacted blocks notify in order ([#8524](https://github.com/paritytech/parity-ethereum/pull/8524))
- Ethcore, rpc, machine: refactor block reward application and tracing ([#8490](https://github.com/paritytech/parity-ethereum/pull/8490))
- Consolidate crypto functionality in `ethcore-crypto`. ([#8432](https://github.com/paritytech/parity-ethereum/pull/8432))
- Eip 145: Bitwise shifting instructions in EVM ([#8451](https://github.com/paritytech/parity-ethereum/pull/8451))
- Remove expect ([#8536](https://github.com/paritytech/parity-ethereum/pull/8536))
- Don't panic in import_block if invalid rlp ([#8522](https://github.com/paritytech/parity-ethereum/pull/8522))
- Pass on storage keys tracing to handle the case when it is not modified ([#8491](https://github.com/paritytech/parity-ethereum/pull/8491))
- Fetching logs by hash in blockchain database ([#8463](https://github.com/paritytech/parity-ethereum/pull/8463))
- Transaction Pool improvements ([#8470](https://github.com/paritytech/parity-ethereum/pull/8470))
- More changes for Android ([#8421](https://github.com/paritytech/parity-ethereum/pull/8421))
- Enable WebAssembly and Byzantium for Ellaism ([#8520](https://github.com/paritytech/parity-ethereum/pull/8520))
- Secretstore: merge two types of errors into single one + Error::is_non_fatal ([#8357](https://github.com/paritytech/parity-ethereum/pull/8357))
- Hardware Wallet trait ([#8071](https://github.com/paritytech/parity-ethereum/pull/8071))
- Directly return None if tracing is disabled ([#8504](https://github.com/paritytech/parity-ethereum/pull/8504))
- Show imported messages for light client ([#8517](https://github.com/paritytech/parity-ethereum/pull/8517))
- Remove unused dependency `bigint` ([#8505](https://github.com/paritytech/parity-ethereum/pull/8505))
- `duration_ns: u64 -> duration: Duration` ([#8457](https://github.com/paritytech/parity-ethereum/pull/8457))
- Return error if RLP size of transaction exceeds the limit ([#8473](https://github.com/paritytech/parity-ethereum/pull/8473))
- Remove three old warp boot nodes. ([#8497](https://github.com/paritytech/parity-ethereum/pull/8497))
- Update wasmi and pwasm-utils ([#8493](https://github.com/paritytech/parity-ethereum/pull/8493))
- Update hardcodedSync for Ethereum, Kovan, and Ropsten ([#8489](https://github.com/paritytech/parity-ethereum/pull/8489))
- Fix snap builds ([#8483](https://github.com/paritytech/parity-ethereum/pull/8483))
- Bump master to 1.12 ([#8477](https://github.com/paritytech/parity-ethereum/pull/8477))
- Don't require write lock when fetching status. ([#8481](https://github.com/paritytech/parity-ethereum/pull/8481))
- Use rename_all for RichBlock and RichHeader serialization ([#8471](https://github.com/paritytech/parity-ethereum/pull/8471))

View File

@@ -16,11 +16,11 @@ crossbeam = "0.3"
ethash = { path = "../ethash" }
ethcore-bloom-journal = { path = "../util/bloom" }
parity-bytes = "0.1"
hashdb = "0.2.1"
memorydb = "0.2.1"
patricia-trie = "0.2"
hashdb = "0.3.0"
memorydb = "0.3.0"
patricia-trie = "0.3.0"
patricia-trie-ethereum = { path = "../util/patricia-trie-ethereum" }
parity-crypto = "0.1"
parity-crypto = "0.2"
error-chain = { version = "0.12", default-features = false }
ethcore-io = { path = "../util/io" }
ethcore-logger = { path = "../logger" }
@@ -29,9 +29,9 @@ ethcore-stratum = { path = "./stratum", optional = true }
ethcore-transaction = { path = "./transaction" }
ethereum-types = "0.4"
memory-cache = { path = "../util/memory_cache" }
ethabi = "5.1.2"
ethabi-derive = "5.1.3"
ethabi-contract = "5.1.1"
ethabi = "6.0"
ethabi-derive = "6.0"
ethabi-contract = "6.0"
ethjson = { path = "../json" }
ethkey = { path = "../ethkey" }
ethstore = { path = "../ethstore" }
@@ -47,7 +47,7 @@ parity-machine = { path = "../machine" }
parking_lot = "0.6"
rayon = "1.0"
rand = "0.4"
rlp = { version = "0.2.4", features = ["ethereum"] }
rlp = { version = "0.3.0", features = ["ethereum"] }
rlp_compress = { path = "../util/rlp_compress" }
rlp_derive = { path = "../util/rlp_derive" }
kvdb = "0.1"
@@ -76,6 +76,7 @@ hardware-wallet = { path = "../hw" }
fake-hardware-wallet = { path = "../util/fake-hardware-wallet" }
[dev-dependencies]
env_logger = "0.4"
tempdir = "0.3"
trie-standardmap = "0.1"
@@ -102,6 +103,8 @@ evm-debug-tests = ["evm-debug", "evm/evm-debug-tests"]
slow-blocks = []
# Run JSON consensus tests.
json-tests = ["ethcore-transaction/json-tests", "test-helpers", "tempdir"]
# Skip JSON consensus tests with pending issues.
ci-skip-issue = []
# Run memory/cpu heavy tests.
test-heavy = []
# Compile benches

View File

@@ -25,12 +25,10 @@ extern crate ethereum_types;
extern crate parity_bytes as bytes;
extern crate rustc_hex;
use std::collections::BTreeMap;
use bytes::BytesRef;
use ethcore::builtin::Builtin;
use ethcore::machine::EthereumMachine;
use ethereum_types::{Address, U256};
use ethereum_types::U256;
use ethcore::ethereum::new_byzantium_test_machine;
use rustc_hex::FromHex;
use self::test::Bencher;

View File

@@ -62,8 +62,8 @@ impl Finalize for Error {
}
/// Cost calculation type. For low-gas usage we calculate costs using usize instead of U256
pub trait CostType: Sized + From<usize> + Copy
+ ops::Mul<Output=Self> + ops::Div<Output=Self> + ops::Add<Output=Self> +ops::Sub<Output=Self>
pub trait CostType: Sized + From<usize> + Copy + Send
+ ops::Mul<Output=Self> + ops::Div<Output=Self> + ops::Add<Output=Self> + ops::Sub<Output=Self>
+ ops::Shr<usize, Output=Self> + ops::Shl<usize, Output=Self>
+ cmp::Ord + fmt::Debug {
/// Converts this cost into `U256`

View File

@@ -17,7 +17,7 @@
//! Evm factory.
//!
use std::sync::Arc;
use vm::{Vm, Schedule};
use vm::{Exec, Schedule};
use ethereum_types::U256;
use super::vm::ActionParams;
use super::interpreter::SharedCache;
@@ -33,7 +33,7 @@ pub struct Factory {
impl Factory {
/// Create fresh instance of VM
/// Might choose implementation depending on supplied gas.
pub fn create(&self, params: ActionParams, schedule: &Schedule, depth: usize) -> Box<Vm> {
pub fn create(&self, params: ActionParams, schedule: &Schedule, depth: usize) -> Box<Exec> {
match self.evm {
VMType::Interpreter => if Self::can_fit_in_usize(&params.gas) {
Box::new(super::interpreter::Interpreter::<usize>::new(params, self.evm_cache.clone(), schedule, depth))

View File

@@ -45,7 +45,7 @@ macro_rules! enum_with_from_u8 {
enum_with_from_u8! {
#[doc = "Virtual machine bytecode instruction."]
#[repr(u8)]
#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Debug)]
#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Debug, Hash)]
pub enum Instruction {
#[doc = "halts execution"]
STOP = 0x00,

View File

@@ -42,7 +42,7 @@ mod inner {
use ethereum_types::U256;
use interpreter::stack::Stack;
use instructions::{Instruction, InstructionInfo, INSTRUCTIONS};
use instructions::{Instruction, InstructionInfo};
use CostType;
macro_rules! evm_debug {
@@ -97,7 +97,7 @@ mod inner {
&self.spacing,
pc,
Self::color(instruction, info.name),
instruction,
instruction as u8,
current_gas,
Self::as_micro(&time),
));
@@ -117,18 +117,16 @@ mod inner {
pub fn done(&mut self) {
// Print out stats
let infos = &*INSTRUCTIONS;
let mut stats: Vec<(_,_)> = self.stats.drain().collect();
stats.sort_by(|ref a, ref b| b.1.avg().cmp(&a.1.avg()));
print(format!("\n{}-------OPCODE STATS:", self.spacing));
for (instruction, stats) in stats.into_iter() {
let info = infos[instruction as usize];
let info = instruction.info();
print(format!("{}-------{:>19}(0x{:<2x}) count: {:4}, avg: {:10}μs",
self.spacing,
Self::color(instruction, info.name),
instruction,
instruction as u8,
stats.count,
stats.avg(),
));

View File

@@ -32,7 +32,8 @@ use ethereum_types::{U256, U512, H256, Address};
use vm::{
self, ActionParams, ParamsType, ActionValue, CallType, MessageCallResult,
ContractCreateResult, CreateContractAddress, ReturnData, GasLeft, Schedule
ContractCreateResult, CreateContractAddress, ReturnData, GasLeft, Schedule,
TrapKind, TrapError
};
use evm::CostType;
@@ -103,6 +104,7 @@ enum InstructionResult<Gas> {
apply: bool,
},
StopExecution,
Trap(TrapKind),
}
enum Never {}
@@ -161,6 +163,7 @@ pub enum InterpreterResult {
Done(vm::Result<GasLeft>),
/// The VM can continue to run.
Continue,
Trap(TrapKind),
}
impl From<vm::Error> for InterpreterResult {
@@ -182,22 +185,89 @@ pub struct Interpreter<Cost: CostType> {
valid_jump_destinations: Option<Arc<BitSet>>,
gasometer: Option<Gasometer<Cost>>,
stack: VecStack<U256>,
resume_output_range: Option<(U256, U256)>,
resume_result: Option<InstructionResult<Cost>>,
last_stack_ret_len: usize,
_type: PhantomData<Cost>,
}
impl<Cost: CostType> vm::Vm for Interpreter<Cost> {
fn exec(&mut self, ext: &mut vm::Ext) -> vm::Result<GasLeft> {
impl<Cost: 'static + CostType> vm::Exec for Interpreter<Cost> {
fn exec(mut self: Box<Self>, ext: &mut vm::Ext) -> vm::ExecTrapResult<GasLeft> {
loop {
let result = self.step(ext);
match result {
InterpreterResult::Continue => {},
InterpreterResult::Done(value) => return value,
InterpreterResult::Done(value) => return Ok(value),
InterpreterResult::Trap(trap) => match trap {
TrapKind::Call(params) => {
return Err(TrapError::Call(params, self));
},
TrapKind::Create(params, address) => {
return Err(TrapError::Create(params, address, self));
},
},
InterpreterResult::Stopped => panic!("Attempted to execute an already stopped VM.")
}
}
}
}
impl<Cost: 'static + CostType> vm::ResumeCall for Interpreter<Cost> {
fn resume_call(mut self: Box<Self>, result: MessageCallResult) -> Box<vm::Exec> {
{
let this = &mut *self;
let (out_off, out_size) = this.resume_output_range.take().expect("Box<ResumeCall> is obtained from a call opcode; resume_output_range is always set after those opcodes are executed; qed");
match result {
MessageCallResult::Success(gas_left, data) => {
let output = this.mem.writeable_slice(out_off, out_size);
let len = cmp::min(output.len(), data.len());
(&mut output[..len]).copy_from_slice(&data[..len]);
this.return_data = data;
this.stack.push(U256::one());
this.resume_result = Some(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater than current one")));
},
MessageCallResult::Reverted(gas_left, data) => {
let output = this.mem.writeable_slice(out_off, out_size);
let len = cmp::min(output.len(), data.len());
(&mut output[..len]).copy_from_slice(&data[..len]);
this.return_data = data;
this.stack.push(U256::zero());
this.resume_result = Some(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater than current one")));
},
MessageCallResult::Failed => {
this.stack.push(U256::zero());
this.resume_result = Some(InstructionResult::Ok);
},
}
}
self
}
}
impl<Cost: 'static + CostType> vm::ResumeCreate for Interpreter<Cost> {
fn resume_create(mut self: Box<Self>, result: ContractCreateResult) -> Box<vm::Exec> {
match result {
ContractCreateResult::Created(address, gas_left) => {
self.stack.push(address_to_u256(address));
self.resume_result = Some(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater.")));
},
ContractCreateResult::Reverted(gas_left, return_data) => {
self.stack.push(U256::zero());
self.return_data = return_data;
self.resume_result = Some(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater.")));
},
ContractCreateResult::Failed => {
self.stack.push(U256::zero());
self.resume_result = Some(InstructionResult::Ok);
},
}
self
}
}
impl<Cost: CostType> Interpreter<Cost> {
/// Create a new `Interpreter` instance with shared cache.
pub fn new(mut params: ActionParams, cache: Arc<SharedCache>, schedule: &Schedule, depth: usize) -> Interpreter<Cost> {
@@ -215,6 +285,9 @@ impl<Cost: CostType> Interpreter<Cost> {
do_trace: true,
mem: Vec::new(),
return_data: ReturnData::empty(),
last_stack_ret_len: 0,
resume_output_range: None,
resume_result: None,
_type: PhantomData,
}
}
@@ -244,51 +317,58 @@ impl<Cost: CostType> Interpreter<Cost> {
/// Inner helper function for step.
#[inline(always)]
fn step_inner(&mut self, ext: &mut vm::Ext) -> Result<Never, InterpreterResult> {
let opcode = self.reader.code[self.reader.position];
let instruction = Instruction::from_u8(opcode);
self.reader.position += 1;
let result = match self.resume_result.take() {
Some(result) => result,
None => {
let opcode = self.reader.code[self.reader.position];
let instruction = Instruction::from_u8(opcode);
self.reader.position += 1;
// TODO: make compile-time removable if too much of a performance hit.
self.do_trace = self.do_trace && ext.trace_next_instruction(
self.reader.position - 1, opcode, self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas.as_u256(),
);
// TODO: make compile-time removable if too much of a performance hit.
self.do_trace = self.do_trace && ext.trace_next_instruction(
self.reader.position - 1, opcode, self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas.as_u256(),
);
let instruction = match instruction {
Some(i) => i,
None => return Err(InterpreterResult::Done(Err(vm::Error::BadInstruction {
instruction: opcode
}))),
let instruction = match instruction {
Some(i) => i,
None => return Err(InterpreterResult::Done(Err(vm::Error::BadInstruction {
instruction: opcode
}))),
};
let info = instruction.info();
self.last_stack_ret_len = info.ret;
self.verify_instruction(ext, instruction, info)?;
// Calculate gas cost
let requirements = self.gasometer.as_mut().expect(GASOMETER_PROOF).requirements(ext, instruction, info, &self.stack, self.mem.size())?;
if self.do_trace {
ext.trace_prepare_execute(self.reader.position - 1, opcode, requirements.gas_cost.as_u256(), Self::mem_written(instruction, &self.stack), Self::store_written(instruction, &self.stack));
}
self.gasometer.as_mut().expect(GASOMETER_PROOF).verify_gas(&requirements.gas_cost)?;
self.mem.expand(requirements.memory_required_size);
self.gasometer.as_mut().expect(GASOMETER_PROOF).current_mem_gas = requirements.memory_total_gas;
self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas = self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas - requirements.gas_cost;
evm_debug!({ self.informant.before_instruction(self.reader.position, instruction, info, &self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas, &self.stack) });
// Execute instruction
let current_gas = self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas;
let result = self.exec_instruction(
current_gas, ext, instruction, requirements.provide_gas
)?;
evm_debug!({ self.informant.after_instruction(instruction) });
result
},
};
let info = instruction.info();
self.verify_instruction(ext, instruction, info)?;
// Calculate gas cost
let requirements = self.gasometer.as_mut().expect(GASOMETER_PROOF).requirements(ext, instruction, info, &self.stack, self.mem.size())?;
if self.do_trace {
ext.trace_prepare_execute(self.reader.position - 1, opcode, requirements.gas_cost.as_u256());
if let InstructionResult::Trap(trap) = result {
return Err(InterpreterResult::Trap(trap));
}
self.gasometer.as_mut().expect(GASOMETER_PROOF).verify_gas(&requirements.gas_cost)?;
self.mem.expand(requirements.memory_required_size);
self.gasometer.as_mut().expect(GASOMETER_PROOF).current_mem_gas = requirements.memory_total_gas;
self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas = self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas - requirements.gas_cost;
evm_debug!({ informant.before_instruction(reader.position, instruction, info, &self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas, &stack) });
let (mem_written, store_written) = match self.do_trace {
true => (Self::mem_written(instruction, &self.stack), Self::store_written(instruction, &self.stack)),
false => (None, None),
};
// Execute instruction
let current_gas = self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas;
let result = self.exec_instruction(
current_gas, ext, instruction, requirements.provide_gas
)?;
evm_debug!({ informant.after_instruction(instruction) });
if let InstructionResult::UnusedGas(ref gas) = result {
self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas = self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas + *gas;
}
@@ -296,9 +376,8 @@ impl<Cost: CostType> Interpreter<Cost> {
if self.do_trace {
ext.trace_executed(
self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas.as_u256(),
self.stack.peek_top(info.ret),
mem_written.map(|(o, s)| (o, &(self.mem[o..o+s]))),
store_written,
self.stack.peek_top(self.last_stack_ret_len),
&self.mem,
);
}
@@ -450,21 +529,24 @@ impl<Cost: CostType> Interpreter<Cost> {
let contract_code = self.mem.read_slice(init_off, init_size);
let create_result = ext.create(&create_gas.as_u256(), &endowment, contract_code, address_scheme);
let create_result = ext.create(&create_gas.as_u256(), &endowment, contract_code, address_scheme, true);
return match create_result {
ContractCreateResult::Created(address, gas_left) => {
Ok(ContractCreateResult::Created(address, gas_left)) => {
self.stack.push(address_to_u256(address));
Ok(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater.")))
},
ContractCreateResult::Reverted(gas_left, return_data) => {
Ok(ContractCreateResult::Reverted(gas_left, return_data)) => {
self.stack.push(U256::zero());
self.return_data = return_data;
Ok(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater.")))
},
ContractCreateResult::Failed => {
Ok(ContractCreateResult::Failed) => {
self.stack.push(U256::zero());
Ok(InstructionResult::Ok)
},
Err(trap) => {
Ok(InstructionResult::Trap(trap))
},
};
},
instructions::CALL | instructions::CALLCODE | instructions::DELEGATECALL | instructions::STATICCALL => {
@@ -523,13 +605,14 @@ impl<Cost: CostType> Interpreter<Cost> {
let call_result = {
let input = self.mem.read_slice(in_off, in_size);
ext.call(&call_gas.as_u256(), sender_address, receive_address, value, input, &code_address, call_type)
ext.call(&call_gas.as_u256(), sender_address, receive_address, value, input, &code_address, call_type, true)
};
let output = self.mem.writeable_slice(out_off, out_size);
self.resume_output_range = Some((out_off, out_size));
return match call_result {
MessageCallResult::Success(gas_left, data) => {
Ok(MessageCallResult::Success(gas_left, data)) => {
let output = self.mem.writeable_slice(out_off, out_size);
let len = cmp::min(output.len(), data.len());
(&mut output[..len]).copy_from_slice(&data[..len]);
@@ -537,7 +620,8 @@ impl<Cost: CostType> Interpreter<Cost> {
self.return_data = data;
Ok(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater than current one")))
},
MessageCallResult::Reverted(gas_left, data) => {
Ok(MessageCallResult::Reverted(gas_left, data)) => {
let output = self.mem.writeable_slice(out_off, out_size);
let len = cmp::min(output.len(), data.len());
(&mut output[..len]).copy_from_slice(&data[..len]);
@@ -545,10 +629,13 @@ impl<Cost: CostType> Interpreter<Cost> {
self.return_data = data;
Ok(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater than current one")))
},
MessageCallResult::Failed => {
Ok(MessageCallResult::Failed) => {
self.stack.push(U256::zero());
Ok(InstructionResult::Ok)
},
Err(trap) => {
Ok(InstructionResult::Trap(trap))
},
};
},
instructions::RETURN => {
@@ -1094,10 +1181,10 @@ mod tests {
use rustc_hex::FromHex;
use vmtype::VMType;
use factory::Factory;
use vm::{self, Vm, ActionParams, ActionValue};
use vm::{self, Exec, ActionParams, ActionValue};
use vm::tests::{FakeExt, test_finalize};
fn interpreter(params: ActionParams, ext: &vm::Ext) -> Box<Vm> {
fn interpreter(params: ActionParams, ext: &vm::Ext) -> Box<Exec> {
Factory::new(VMType::Interpreter, 1).create(params, ext.schedule(), ext.depth())
}
@@ -1117,7 +1204,7 @@ mod tests {
let gas_left = {
let mut vm = interpreter(params, &ext);
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_eq!(ext.calls.len(), 1);
@@ -1139,7 +1226,7 @@ mod tests {
let err = {
let mut vm = interpreter(params, &ext);
test_finalize(vm.exec(&mut ext)).err().unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).err().unwrap()
};
assert_eq!(err, ::vm::Error::OutOfBounds);

View File

@@ -39,7 +39,7 @@ fn test_add(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_eq!(gas_left, U256::from(79_988));
@@ -59,7 +59,7 @@ fn test_sha3(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_eq!(gas_left, U256::from(79_961));
@@ -79,7 +79,7 @@ fn test_address(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_eq!(gas_left, U256::from(79_995));
@@ -101,7 +101,7 @@ fn test_origin(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_eq!(gas_left, U256::from(79_995));
@@ -123,7 +123,7 @@ fn test_sender(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_eq!(gas_left, U256::from(79_995));
@@ -158,7 +158,7 @@ fn test_extcodecopy(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_eq!(gas_left, U256::from(79_935));
@@ -178,7 +178,7 @@ fn test_log_empty(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_eq!(gas_left, U256::from(99_619));
@@ -210,7 +210,7 @@ fn test_log_sender(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_eq!(gas_left, U256::from(98_974));
@@ -235,7 +235,7 @@ fn test_blockhash(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_eq!(gas_left, U256::from(79_974));
@@ -257,7 +257,7 @@ fn test_calldataload(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_eq!(gas_left, U256::from(79_991));
@@ -278,7 +278,7 @@ fn test_author(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_eq!(gas_left, U256::from(79_995));
@@ -298,7 +298,7 @@ fn test_timestamp(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_eq!(gas_left, U256::from(79_995));
@@ -318,7 +318,7 @@ fn test_number(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_eq!(gas_left, U256::from(79_995));
@@ -338,7 +338,7 @@ fn test_difficulty(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_eq!(gas_left, U256::from(79_995));
@@ -358,7 +358,7 @@ fn test_gas_limit(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_eq!(gas_left, U256::from(79_995));
@@ -376,7 +376,7 @@ fn test_mul(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_store(&ext, 0, "000000000000000000000000000000000000000000000000734349397b853383");
@@ -394,7 +394,7 @@ fn test_sub(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000012364ad0302");
@@ -412,7 +412,7 @@ fn test_div(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_store(&ext, 0, "000000000000000000000000000000000000000000000000000000000002e0ac");
@@ -430,7 +430,7 @@ fn test_div_zero(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000000");
@@ -448,7 +448,7 @@ fn test_mod(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000076b4b");
@@ -467,7 +467,7 @@ fn test_smod(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000076b4b");
@@ -486,7 +486,7 @@ fn test_sdiv(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_store(&ext, 0, "000000000000000000000000000000000000000000000000000000000002e0ac");
@@ -505,7 +505,7 @@ fn test_exp(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_store(&ext, 0, "90fd23767b60204c3d6fc8aec9e70a42a3f127140879c133a20129a597ed0c59");
@@ -525,7 +525,7 @@ fn test_comparison(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000000");
@@ -546,7 +546,7 @@ fn test_signed_comparison(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000000");
@@ -567,7 +567,7 @@ fn test_bitops(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_store(&ext, 0, "00000000000000000000000000000000000000000000000000000000000000f0");
@@ -590,7 +590,7 @@ fn test_addmod_mulmod(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000001");
@@ -611,7 +611,7 @@ fn test_byte(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000000");
@@ -630,7 +630,7 @@ fn test_signextend(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000fff");
@@ -650,7 +650,7 @@ fn test_badinstruction_int() {
let err = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap_err()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap_err()
};
match err {
@@ -670,7 +670,7 @@ fn test_pop(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_store(&ext, 0, "00000000000000000000000000000000000000000000000000000000000000f0");
@@ -690,7 +690,7 @@ fn test_extops(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000004"); // PC / CALLDATASIZE
@@ -713,7 +713,7 @@ fn test_jumps(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_eq!(ext.sstore_clears, ext.schedule().sstore_refund_gas as i128);
@@ -741,7 +741,7 @@ fn test_calls(factory: super::Factory) {
let gas_left = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_set_contains(&ext.calls, &FakeCall {
@@ -782,7 +782,7 @@ fn test_create_in_staticcall(factory: super::Factory) {
let err = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap_err()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap_err()
};
assert_eq!(err, vm::Error::MutableCallInStaticContext);
@@ -1050,7 +1050,7 @@ fn push_two_pop_one_constantinople_test(factory: &super::Factory, opcode: u8, pu
let _ = {
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap()
};
assert_store(&ext, 0, result);

View File

@@ -12,18 +12,18 @@ ethcore = { path = ".."}
parity-bytes = "0.1"
ethcore-transaction = { path = "../transaction" }
ethereum-types = "0.4"
memorydb = "0.2.1"
patricia-trie = "0.2"
memorydb = "0.3.0"
patricia-trie = "0.3.0"
patricia-trie-ethereum = { path = "../../util/patricia-trie-ethereum" }
ethcore-network = { path = "../../util/network" }
ethcore-io = { path = "../../util/io" }
hashdb = "0.2.1"
hashdb = "0.3.0"
heapsize = "0.4"
vm = { path = "../vm" }
fastmap = { path = "../../util/fastmap" }
rlp = { version = "0.2.4", features = ["ethereum"] }
rlp = { version = "0.3.0", features = ["ethereum"] }
rlp_derive = { path = "../../util/rlp_derive" }
smallvec = "0.4"
smallvec = "0.6"
futures = "0.1"
rand = "0.4"
itertools = "0.5"

View File

@@ -27,6 +27,7 @@ use ethcore::ids::BlockId;
use ethereum_types::{H256, U256};
use hashdb::HashDB;
use keccak_hasher::KeccakHasher;
use kvdb::DBValue;
use memorydb::MemoryDB;
use bytes::Bytes;
use trie::{TrieMut, Trie, Recorder};
@@ -52,13 +53,13 @@ pub const SIZE: u64 = 2048;
/// A canonical hash trie. This is generic over any database it can query.
/// See module docs for more details.
#[derive(Debug, Clone)]
pub struct CHT<DB: HashDB<KeccakHasher>> {
pub struct CHT<DB: HashDB<KeccakHasher, DBValue>> {
db: DB,
root: H256, // the root of this CHT.
number: u64,
}
impl<DB: HashDB<KeccakHasher>> CHT<DB> {
impl<DB: HashDB<KeccakHasher, DBValue>> CHT<DB> {
/// Query the root of the CHT.
pub fn root(&self) -> H256 { self.root }
@@ -92,10 +93,10 @@ pub struct BlockInfo {
/// Build an in-memory CHT from a closure which provides necessary information
/// about blocks. If the fetcher ever fails to provide the info, the CHT
/// will not be generated.
pub fn build<F>(cht_num: u64, mut fetcher: F) -> Option<CHT<MemoryDB<KeccakHasher>>>
pub fn build<F>(cht_num: u64, mut fetcher: F) -> Option<CHT<MemoryDB<KeccakHasher, DBValue>>>
where F: FnMut(BlockId) -> Option<BlockInfo>
{
let mut db = MemoryDB::<KeccakHasher>::new();
let mut db = MemoryDB::<KeccakHasher, DBValue>::new();
// start from the last block by number and work backwards.
let last_num = start_number(cht_num + 1) - 1;
@@ -134,7 +135,7 @@ pub fn compute_root<I>(cht_num: u64, iterable: I) -> Option<H256>
let start_num = start_number(cht_num) as usize;
for (i, (h, td)) in iterable.into_iter().take(SIZE as usize).enumerate() {
v.push((key!(i + start_num).into_vec(), val!(h, td).into_vec()))
v.push((key!(i + start_num), val!(h, td)))
}
if v.len() == SIZE as usize {
@@ -149,7 +150,7 @@ pub fn compute_root<I>(cht_num: u64, iterable: I) -> Option<H256>
/// verify the given trie branch and extract the canonical hash and total difficulty.
// TODO: better support for partially-checked queries.
pub fn check_proof(proof: &[Bytes], num: u64, root: H256) -> Option<(H256, U256)> {
let mut db = MemoryDB::<KeccakHasher>::new();
let mut db = MemoryDB::<KeccakHasher, DBValue>::new();
for node in proof { db.insert(&node[..]); }
let res = match TrieDB::new(&db, &root) {

View File

@@ -33,7 +33,7 @@ use cht;
use ethcore::block_status::BlockStatus;
use ethcore::encoded;
use ethcore::engines::epoch::{Transition as EpochTransition, PendingTransition as PendingEpochTransition};
use ethcore::error::{Error, BlockImportError, BlockImportErrorKind, BlockError};
use ethcore::error::{Error, EthcoreResult, ErrorKind as EthcoreErrorKind, BlockError};
use ethcore::header::Header;
use ethcore::ids::BlockId;
use ethcore::spec::{Spec, SpecHardcodedSync};
@@ -218,7 +218,7 @@ impl HeaderChain {
) -> Result<Self, Error> {
let mut live_epoch_proofs = ::std::collections::HashMap::default();
let genesis = ::rlp::encode(&spec.genesis_header()).into_vec();
let genesis = ::rlp::encode(&spec.genesis_header());
let decoded_header = spec.genesis_header();
let chain = if let Some(current) = db.get(col, CURRENT_KEY)? {
@@ -351,7 +351,7 @@ impl HeaderChain {
transaction: &mut DBTransaction,
header: &Header,
transition_proof: Option<Vec<u8>>,
) -> Result<PendingChanges, BlockImportError> {
) -> EthcoreResult<PendingChanges> {
self.insert_inner(transaction, header, None, transition_proof)
}
@@ -364,7 +364,7 @@ impl HeaderChain {
header: &Header,
total_difficulty: U256,
transition_proof: Option<Vec<u8>>,
) -> Result<PendingChanges, BlockImportError> {
) -> EthcoreResult<PendingChanges> {
self.insert_inner(transaction, header, Some(total_difficulty), transition_proof)
}
@@ -374,7 +374,7 @@ impl HeaderChain {
header: &Header,
total_difficulty: Option<U256>,
transition_proof: Option<Vec<u8>>,
) -> Result<PendingChanges, BlockImportError> {
) -> EthcoreResult<PendingChanges> {
let hash = header.hash();
let number = header.number();
let parent_hash = *header.parent_hash();
@@ -403,7 +403,7 @@ impl HeaderChain {
.and_then(|entry| entry.candidates.iter().find(|c| c.hash == parent_hash))
.map(|c| c.total_difficulty)
.ok_or_else(|| BlockError::UnknownParent(parent_hash))
.map_err(BlockImportErrorKind::Block)?
.map_err(EthcoreErrorKind::Block)?
};
parent_td + *header.difficulty()

View File

@@ -22,7 +22,7 @@ use ethcore::block_status::BlockStatus;
use ethcore::client::{ClientReport, EnvInfo, ClientIoMessage};
use ethcore::engines::{epoch, EthEngine, EpochChange, EpochTransition, Proof};
use ethcore::machine::EthereumMachine;
use ethcore::error::{Error, BlockImportError};
use ethcore::error::{Error, EthcoreResult};
use ethcore::ids::BlockId;
use ethcore::header::{BlockNumber, Header};
use ethcore::verification::queue::{self, HeaderQueue};
@@ -85,7 +85,7 @@ pub trait LightChainClient: Send + Sync {
/// Queue header to be verified. Required that all headers queued have their
/// parent queued prior.
fn queue_header(&self, header: Header) -> Result<H256, BlockImportError>;
fn queue_header(&self, header: Header) -> EthcoreResult<H256>;
/// Attempt to get a block hash by block id.
fn block_hash(&self, id: BlockId) -> Option<H256>;
@@ -206,8 +206,8 @@ impl<T: ChainDataFetcher> Client<T> {
}
/// Import a header to the queue for additional verification.
pub fn import_header(&self, header: Header) -> Result<H256, BlockImportError> {
self.queue.import(header).map_err(Into::into)
pub fn import_header(&self, header: Header) -> EthcoreResult<H256> {
self.queue.import(header).map_err(|(_, e)| e)
}
/// Inquire about the status of a given header.
@@ -313,7 +313,7 @@ impl<T: ChainDataFetcher> Client<T> {
The node may not be able to synchronize further.", e);
}
let epoch_proof = self.engine.is_epoch_end(
let epoch_proof = self.engine.is_epoch_end_light(
&verified_header,
&|h| self.chain.block_header(BlockId::Hash(h)).and_then(|hdr| hdr.decode().ok()),
&|h| self.chain.pending_transition(h),
@@ -526,7 +526,7 @@ impl<T: ChainDataFetcher> LightChainClient for Client<T> {
fn chain_info(&self) -> BlockChainInfo { Client::chain_info(self) }
fn queue_header(&self, header: Header) -> Result<H256, BlockImportError> {
fn queue_header(&self, header: Header) -> EthcoreResult<H256> {
self.import_header(header)
}

View File

@@ -28,7 +28,7 @@ use parking_lot::{Mutex, RwLock};
use provider::Provider;
use request::{Request, NetworkRequests as Requests, Response};
use rlp::{RlpStream, Rlp};
use std::collections::{HashMap, HashSet};
use std::collections::{HashMap, HashSet, VecDeque};
use std::fmt;
use std::ops::{BitOr, BitAnd, Not};
use std::sync::Arc;
@@ -38,7 +38,7 @@ use std::time::{Duration, Instant};
use self::request_credits::{Credits, FlowParams};
use self::context::{Ctx, TickCtx};
use self::error::Punishment;
use self::load_timer::{LoadDistribution, NullStore};
use self::load_timer::{LoadDistribution, NullStore, MOVING_SAMPLE_SIZE};
use self::request_set::RequestSet;
use self::id_guard::IdGuard;
@@ -70,6 +70,16 @@ const PROPAGATE_TIMEOUT_INTERVAL: Duration = Duration::from_secs(5);
const RECALCULATE_COSTS_TIMEOUT: TimerToken = 3;
const RECALCULATE_COSTS_INTERVAL: Duration = Duration::from_secs(60 * 60);
const STATISTICS_TIMEOUT: TimerToken = 4;
const STATISTICS_INTERVAL: Duration = Duration::from_secs(15);
/// Maximum load share for the light server
pub const MAX_LIGHTSERV_LOAD: f64 = 0.5;
/// Factor to multiply leecher count to cater for
/// extra sudden connections (should be >= 1.0)
pub const LEECHER_COUNT_FACTOR: f64 = 1.25;
// minimum interval between updates.
const UPDATE_INTERVAL: Duration = Duration::from_millis(5000);
@@ -256,18 +266,18 @@ pub trait Handler: Send + Sync {
pub struct Config {
/// How many stored seconds of credits peers should be able to accumulate.
pub max_stored_seconds: u64,
/// How much of the total load capacity each peer should be allowed to take.
pub load_share: f64,
/// The network config median peers (used as default peer count)
pub median_peers: f64,
}
impl Default for Config {
fn default() -> Self {
const LOAD_SHARE: f64 = 1.0 / 25.0;
const MEDIAN_PEERS: f64 = 25.0;
const MAX_ACCUMULATED: u64 = 60 * 5; // only charge for 5 minutes.
Config {
max_stored_seconds: MAX_ACCUMULATED,
load_share: LOAD_SHARE,
median_peers: MEDIAN_PEERS,
}
}
}
@@ -335,6 +345,42 @@ mod id_guard {
}
}
/// Provides various statistics that could
/// be used to compute costs
pub struct Statistics {
/// Samples of peer count
peer_counts: VecDeque<usize>,
}
impl Statistics {
/// Create a new Statistics instance
pub fn new() -> Self {
Statistics {
peer_counts: VecDeque::with_capacity(MOVING_SAMPLE_SIZE),
}
}
/// Add a new peer_count sample
pub fn add_peer_count(&mut self, peer_count: usize) {
while self.peer_counts.len() >= MOVING_SAMPLE_SIZE {
self.peer_counts.pop_front();
}
self.peer_counts.push_back(peer_count);
}
/// Get the average peer count from previous samples. Is always >= 1.0
pub fn avg_peer_count(&self) -> f64 {
let len = self.peer_counts.len();
if len == 0 {
return 1.0;
}
let avg = self.peer_counts.iter()
.fold(0, |sum: u32, &v| sum.saturating_add(v as u32)) as f64
/ len as f64;
avg.max(1.0)
}
}
/// This is an implementation of the light ethereum network protocol, abstracted
/// over a `Provider` of data and a p2p network.
///
@@ -359,6 +405,7 @@ pub struct LightProtocol {
req_id: AtomicUsize,
sample_store: Box<SampleStore>,
load_distribution: LoadDistribution,
statistics: RwLock<Statistics>,
}
impl LightProtocol {
@@ -369,9 +416,11 @@ impl LightProtocol {
let genesis_hash = provider.chain_info().genesis_hash;
let sample_store = params.sample_store.unwrap_or_else(|| Box::new(NullStore));
let load_distribution = LoadDistribution::load(&*sample_store);
// Default load share relative to median peers
let load_share = MAX_LIGHTSERV_LOAD / params.config.median_peers;
let flow_params = FlowParams::from_request_times(
|kind| load_distribution.expected_time(kind),
params.config.load_share,
load_share,
Duration::from_secs(params.config.max_stored_seconds),
);
@@ -389,6 +438,7 @@ impl LightProtocol {
req_id: AtomicUsize::new(0),
sample_store,
load_distribution,
statistics: RwLock::new(Statistics::new()),
}
}
@@ -408,6 +458,16 @@ impl LightProtocol {
)
}
/// Get the number of active light peers downloading from the
/// node
pub fn leecher_count(&self) -> usize {
let credit_limit = *self.flow_params.read().limit();
// Count the number of peers that used some credit
self.peers.read().iter()
.filter(|(_, p)| p.lock().local_credits.current() < credit_limit)
.count()
}
/// Make a request to a peer.
///
/// Fails on: nonexistent peer, network error, peer not server,
@@ -772,12 +832,16 @@ impl LightProtocol {
fn begin_new_cost_period(&self, io: &IoContext) {
self.load_distribution.end_period(&*self.sample_store);
let avg_peer_count = self.statistics.read().avg_peer_count();
// Load share relative to average peer count +LEECHER_COUNT_FACTOR%
let load_share = MAX_LIGHTSERV_LOAD / (avg_peer_count * LEECHER_COUNT_FACTOR);
let new_params = Arc::new(FlowParams::from_request_times(
|kind| self.load_distribution.expected_time(kind),
self.config.load_share,
load_share,
Duration::from_secs(self.config.max_stored_seconds),
));
*self.flow_params.write() = new_params.clone();
trace!(target: "pip", "New cost period: avg_peers={} ; cost_table:{:?}", avg_peer_count, new_params.cost_table());
let peers = self.peers.read();
let now = Instant::now();
@@ -797,6 +861,11 @@ impl LightProtocol {
peer_info.awaiting_acknowledge = Some((now, new_params.clone()));
}
}
fn tick_statistics(&self) {
let leecher_count = self.leecher_count();
self.statistics.write().add_peer_count(leecher_count);
}
}
impl LightProtocol {
@@ -1099,6 +1168,8 @@ impl NetworkProtocolHandler for LightProtocol {
.expect("Error registering sync timer.");
io.register_timer(RECALCULATE_COSTS_TIMEOUT, RECALCULATE_COSTS_INTERVAL)
.expect("Error registering request timer interval token.");
io.register_timer(STATISTICS_TIMEOUT, STATISTICS_INTERVAL)
.expect("Error registering statistics timer.");
}
fn read(&self, io: &NetworkContext, peer: &PeerId, packet_id: u8, data: &[u8]) {
@@ -1119,6 +1190,7 @@ impl NetworkProtocolHandler for LightProtocol {
TICK_TIMEOUT => self.tick_handlers(&io),
PROPAGATE_TIMEOUT => self.propagate_transactions(&io),
RECALCULATE_COSTS_TIMEOUT => self.begin_new_cost_period(&io),
STATISTICS_TIMEOUT => self.tick_statistics(),
_ => warn!(target: "pip", "received timeout on unknown token {}", timer),
}
}

View File

@@ -22,9 +22,10 @@ use ethcore::client::{EachBlockWith, TestBlockChainClient};
use ethcore::encoded;
use ethcore::ids::BlockId;
use ethereum_types::{H256, U256, Address};
use net::{LightProtocol, Params, packet, Peer};
use net::{LightProtocol, Params, packet, Peer, Statistics};
use net::context::IoContext;
use net::status::{Capabilities, Status};
use net::load_timer::MOVING_SAMPLE_SIZE;
use network::{PeerId, NodeId};
use provider::Provider;
use request;
@@ -150,7 +151,7 @@ impl Provider for TestProvider {
fn storage_proof(&self, req: request::CompleteStorageRequest) -> Option<request::StorageResponse> {
Some(StorageResponse {
proof: vec![::rlp::encode(&req.key_hash).into_vec()],
proof: vec![::rlp::encode(&req.key_hash)],
value: req.key_hash | req.address_hash,
})
}
@@ -780,3 +781,34 @@ fn get_transaction_index() {
let expected = Expect::Respond(packet::RESPONSE, response);
proto.handle_packet(&expected, 1, packet::REQUEST, &request_body);
}
#[test]
fn sync_statistics() {
let mut stats = Statistics::new();
// Empty set should return 1.0
assert_eq!(stats.avg_peer_count(), 1.0);
// Average < 1.0 should return 1.0
stats.add_peer_count(0);
assert_eq!(stats.avg_peer_count(), 1.0);
stats = Statistics::new();
const N: f64 = 50.0;
for i in 1..(N as usize + 1) {
stats.add_peer_count(i);
}
// Compute the average for the sum 1..N
assert_eq!(stats.avg_peer_count(), N * (N + 1.0) / 2.0 / N);
for _ in 1..(MOVING_SAMPLE_SIZE + 1) {
stats.add_peer_count(40);
}
// Test that it returns the average of the last
// `MOVING_SAMPLE_SIZE` values
assert_eq!(stats.avg_peer_count(), 40.0);
}

View File

@@ -19,17 +19,18 @@
//! will take the raw data received here and extract meaningful results from it.
use std::cmp;
use std::collections::HashMap;
use std::collections::{HashMap, BTreeSet};
use std::marker::PhantomData;
use std::sync::Arc;
use ethcore::executed::{Executed, ExecutionError};
use futures::{Poll, Future};
use futures::sync::oneshot::{self, Receiver, Canceled};
use futures::{Poll, Future, Async};
use futures::sync::oneshot::{self, Receiver};
use network::PeerId;
use parking_lot::{RwLock, Mutex};
use rand;
use std::time::{Duration, SystemTime};
use net::{
self, Handler, PeerStatus, Status, Capabilities,
@@ -49,7 +50,45 @@ pub mod request;
/// The result of execution
pub type ExecutionResult = Result<Executed, ExecutionError>;
/// The default number of retries for OnDemand queries to send to the other nodes
pub const DEFAULT_RETRY_COUNT: usize = 10;
/// The default time limit in milliseconds for inactive (no new peer to connect to) OnDemand queries (0 for unlimited)
pub const DEFAULT_QUERY_TIME_LIMIT: Duration = Duration::from_millis(10000);
const NULL_DURATION: Duration = Duration::from_secs(0);
/// OnDemand related errors
pub mod error {
use futures::sync::oneshot::Canceled;
error_chain! {
foreign_links {
ChannelCanceled(Canceled) #[doc = "Canceled oneshot channel"];
}
errors {
#[doc = "Max number of on-demand query attempts reached without result."]
MaxAttemptReach(query_index: usize) {
description("On-demand query limit reached")
display("On-demand query limit reached on query #{}", query_index)
}
#[doc = "No reply with current peer set, time out occured while waiting for new peers for additional query attempt."]
TimeoutOnNewPeers(query_index: usize, remaining_attempts: usize) {
description("Timeout for On-demand query")
display("Timeout for On-demand query; {} query attempts remain for query #{}", remaining_attempts, query_index)
}
}
}
}
// relevant peer info.
#[derive(Debug, Clone, PartialEq, Eq)]
struct Peer {
status: Status,
capabilities: Capabilities,
@@ -74,13 +113,21 @@ impl Peer {
}
}
/// Either an array of responses or a single error.
type PendingResponse = self::error::Result<Vec<Response>>;
// Attempted request info and sender to put received value.
struct Pending {
requests: basic_request::Batch<CheckedRequest>,
net_requests: basic_request::Batch<NetworkRequest>,
required_capabilities: Capabilities,
responses: Vec<Response>,
sender: oneshot::Sender<Vec<Response>>,
sender: oneshot::Sender<PendingResponse>,
base_query_index: usize,
remaining_query_count: usize,
query_id_history: BTreeSet<PeerId>,
inactive_time_limit: Option<SystemTime>,
}
impl Pending {
@@ -142,7 +189,9 @@ impl Pending {
// if the requests are complete, send the result and consume self.
fn try_complete(self) -> Option<Self> {
if self.requests.is_complete() {
let _ = self.sender.send(self.responses);
if self.sender.send(Ok(self.responses)).is_err() {
debug!(target: "on_demand", "Dropped oneshot channel receiver on complete request at query #{}", self.query_id_history.len());
}
None
} else {
Some(self)
@@ -177,6 +226,25 @@ impl Pending {
self.net_requests = builder.build();
self.required_capabilities = capabilities;
}
// returning no reponse, it will result in an error.
// self is consumed on purpose.
fn no_response(self) {
trace!(target: "on_demand", "Dropping a pending query (no reply) at query #{}", self.query_id_history.len());
let err = self::error::ErrorKind::MaxAttemptReach(self.requests.num_answered());
if self.sender.send(Err(err.into())).is_err() {
debug!(target: "on_demand", "Dropped oneshot channel receiver on no response");
}
}
// returning a peer discovery timeout during query attempts
fn time_out(self) {
trace!(target: "on_demand", "Dropping a pending query (no new peer time out) at query #{}", self.query_id_history.len());
let err = self::error::ErrorKind::TimeoutOnNewPeers(self.requests.num_answered(), self.query_id_history.len());
if self.sender.send(Err(err.into())).is_err() {
debug!(target: "on_demand", "Dropped oneshot channel receiver on time out");
}
}
}
// helper to guess capabilities required for a given batch of network requests.
@@ -230,16 +298,21 @@ fn guess_capabilities(requests: &[CheckedRequest]) -> Capabilities {
/// A future extracting the concrete output type of the generic adapter
/// from a vector of responses.
pub struct OnResponses<T: request::RequestAdapter> {
receiver: Receiver<Vec<Response>>,
receiver: Receiver<PendingResponse>,
_marker: PhantomData<T>,
}
impl<T: request::RequestAdapter> Future for OnResponses<T> {
type Item = T::Out;
type Error = Canceled;
type Error = self::error::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
self.receiver.poll().map(|async| async.map(T::extract_from))
match self.receiver.poll() {
Ok(Async::Ready(Ok(v))) => Ok(Async::Ready(T::extract_from(v))),
Ok(Async::Ready(Err(e))) => Err(e),
Ok(Async::NotReady) => Ok(Async::NotReady),
Err(e) => Err(e.into()),
}
}
}
@@ -253,9 +326,12 @@ pub struct OnDemand {
in_transit: RwLock<HashMap<ReqId, Pending>>,
cache: Arc<Mutex<Cache>>,
no_immediate_dispatch: bool,
base_retry_count: usize,
query_inactive_time_limit: Option<Duration>,
}
impl OnDemand {
/// Create a new `OnDemand` service with the given cache.
pub fn new(cache: Arc<Mutex<Cache>>) -> Self {
OnDemand {
@@ -264,6 +340,8 @@ impl OnDemand {
in_transit: RwLock::new(HashMap::new()),
cache,
no_immediate_dispatch: false,
base_retry_count: DEFAULT_RETRY_COUNT,
query_inactive_time_limit: Some(DEFAULT_QUERY_TIME_LIMIT),
}
}
@@ -282,11 +360,11 @@ impl OnDemand {
/// Fails if back-references are not coherent.
/// The returned vector of responses will correspond to the requests exactly.
pub fn request_raw(&self, ctx: &BasicContext, requests: Vec<Request>)
-> Result<Receiver<Vec<Response>>, basic_request::NoSuchOutput>
-> Result<Receiver<PendingResponse>, basic_request::NoSuchOutput>
{
let (sender, receiver) = oneshot::channel();
if requests.is_empty() {
assert!(sender.send(Vec::new()).is_ok(), "receiver still in scope; qed");
assert!(sender.send(Ok(Vec::new())).is_ok(), "receiver still in scope; qed");
return Ok(receiver);
}
@@ -325,6 +403,10 @@ impl OnDemand {
required_capabilities: capabilities,
responses,
sender,
base_query_index: 0,
remaining_query_count: 0,
query_id_history: BTreeSet::new(),
inactive_time_limit: None,
});
Ok(receiver)
@@ -363,30 +445,68 @@ impl OnDemand {
let peers = self.peers.read();
*pending = ::std::mem::replace(&mut *pending, Vec::new()).into_iter()
.filter(|pending| !pending.sender.is_canceled())
.filter_map(|pending| {
.filter_map(|mut pending| {
// the peer we dispatch to is chosen randomly
let num_peers = peers.len();
let rng = rand::random::<usize>() % cmp::max(num_peers, 1);
for (peer_id, peer) in peers.iter().chain(peers.iter()).skip(rng).take(num_peers) {
let history_len = pending.query_id_history.len();
let offset = if history_len == 0 {
pending.remaining_query_count = self.base_retry_count;
let rand = rand::random::<usize>();
pending.base_query_index = rand;
rand
} else {
pending.base_query_index + history_len
} % cmp::max(num_peers, 1);
let init_remaining_query_count = pending.remaining_query_count; // to fail in case of big reduction of nb of peers
for (peer_id, peer) in peers.iter().chain(peers.iter())
.skip(offset).take(num_peers) {
// TODO: see which requests can be answered by the cache?
if !peer.can_fulfill(&pending.required_capabilities) {
continue
if pending.remaining_query_count == 0 {
break
}
match ctx.request_from(*peer_id, pending.net_requests.clone()) {
Ok(req_id) => {
trace!(target: "on_demand", "Dispatched request {} to peer {}", req_id, peer_id);
self.in_transit.write().insert(req_id, pending);
return None
if pending.query_id_history.insert(peer_id.clone()) {
if !peer.can_fulfill(&pending.required_capabilities) {
trace!(target: "on_demand", "Peer {} without required capabilities, skipping, {} remaining attempts", peer_id, pending.remaining_query_count);
continue
}
pending.remaining_query_count -= 1;
pending.inactive_time_limit = None;
match ctx.request_from(*peer_id, pending.net_requests.clone()) {
Ok(req_id) => {
trace!(target: "on_demand", "Dispatched request {} to peer {}, {} remaining attempts", req_id, peer_id, pending.remaining_query_count);
self.in_transit.write().insert(req_id, pending);
return None
}
Err(net::Error::NoCredits) | Err(net::Error::NotServer) => {}
Err(e) => debug!(target: "on_demand", "Error dispatching request to peer: {}", e),
}
Err(net::Error::NoCredits) | Err(net::Error::NotServer) => {}
Err(e) => debug!(target: "on_demand", "Error dispatching request to peer: {}", e),
}
}
// TODO: maximum number of failures _when we have peers_.
Some(pending)
if pending.remaining_query_count == 0 {
pending.no_response();
None
} else if init_remaining_query_count == pending.remaining_query_count {
if let Some(query_inactive_time_limit) = self.query_inactive_time_limit {
let now = SystemTime::now();
if let Some(inactive_time_limit) = pending.inactive_time_limit {
if now > inactive_time_limit {
pending.time_out();
return None
}
} else {
debug!(target: "on_demand", "No more peers to query, waiting for {} seconds until dropping query", query_inactive_time_limit.as_secs());
pending.inactive_time_limit = Some(now + query_inactive_time_limit);
}
}
Some(pending)
} else {
Some(pending)
}
})
.collect(); // `pending` now contains all requests we couldn't dispatch.
@@ -406,6 +526,21 @@ impl OnDemand {
self.attempt_dispatch(ctx);
}
}
/// Set the retry count for a query.
pub fn default_retry_number(&mut self, nb_retry: usize) {
self.base_retry_count = nb_retry;
}
/// Set the time limit for a query.
pub fn query_inactive_time_limit(&mut self, inactive_time_limit: Duration) {
self.query_inactive_time_limit = if inactive_time_limit == NULL_DURATION {
None
} else {
Some(inactive_time_limit)
};
}
}
impl Handler for OnDemand {
@@ -458,6 +593,16 @@ impl Handler for OnDemand {
None => return,
};
if responses.is_empty() {
if pending.remaining_query_count == 0 {
pending.no_response();
return;
}
} else {
// do not keep query counter for others elements of this batch
pending.query_id_history.clear();
}
// for each incoming response
// 1. ensure verification data filled.
// 2. pending.requests.supply_response

View File

@@ -1156,7 +1156,7 @@ mod tests {
header.set_number(10_000);
header.set_extra_data(b"test_header".to_vec());
let hash = header.hash();
let raw_header = encoded::Header::new(::rlp::encode(&header).into_vec());
let raw_header = encoded::Header::new(::rlp::encode(&header));
let cache = Mutex::new(make_cache());
assert!(HeaderByHash(hash.into()).check_response(&cache, &hash.into(), &[raw_header]).is_ok())
@@ -1177,14 +1177,14 @@ mod tests {
headers.reverse(); // because responses are in reverse order
let raw_headers = headers.iter()
.map(|hdr| encoded::Header::new(::rlp::encode(hdr).into_vec()))
.map(|hdr| encoded::Header::new(::rlp::encode(hdr)))
.collect::<Vec<_>>();
let mut invalid_successor = Header::new();
invalid_successor.set_number(11);
invalid_successor.set_parent_hash(headers[1].hash());
let raw_invalid_successor = encoded::Header::new(::rlp::encode(&invalid_successor).into_vec());
let raw_invalid_successor = encoded::Header::new(::rlp::encode(&invalid_successor));
let cache = Mutex::new(make_cache());
@@ -1247,10 +1247,10 @@ mod tests {
let mut body_stream = RlpStream::new_list(2);
body_stream.begin_list(0).begin_list(0);
let req = Body(encoded::Header::new(::rlp::encode(&header).into_vec()).into());
let req = Body(encoded::Header::new(::rlp::encode(&header)).into());
let cache = Mutex::new(make_cache());
let response = encoded::Body::new(body_stream.drain().into_vec());
let response = encoded::Body::new(body_stream.drain());
assert!(req.check_response(&cache, &response).is_ok())
}
@@ -1270,7 +1270,7 @@ mod tests {
header.set_receipts_root(receipts_root);
let req = BlockReceipts(encoded::Header::new(::rlp::encode(&header).into_vec()).into());
let req = BlockReceipts(encoded::Header::new(::rlp::encode(&header)).into());
let cache = Mutex::new(make_cache());
assert!(req.check_response(&cache, &receipts).is_ok())
@@ -1318,7 +1318,7 @@ mod tests {
header.set_state_root(root.clone());
let req = Account {
header: encoded::Header::new(::rlp::encode(&header).into_vec()).into(),
header: encoded::Header::new(::rlp::encode(&header)).into(),
address: addr,
};
@@ -1332,7 +1332,7 @@ mod tests {
let code_hash = keccak(&code);
let header = Header::new();
let req = Code {
header: encoded::Header::new(::rlp::encode(&header).into_vec()).into(),
header: encoded::Header::new(::rlp::encode(&header)).into(),
code_hash: code_hash.into(),
};

View File

@@ -177,7 +177,7 @@ impl<T: ProvingBlockChainClient + ?Sized> Provider for T {
fn block_receipts(&self, req: request::CompleteReceiptsRequest) -> Option<request::ReceiptsResponse> {
BlockChainClient::block_receipts(self, &req.hash)
.map(|x| ::request::ReceiptsResponse { receipts: ::rlp::decode_list(&x) })
.map(|x| ::request::ReceiptsResponse { receipts: x.receipts })
}
fn account_proof(&self, req: request::CompleteAccountRequest) -> Option<request::AccountResponse> {

View File

@@ -1676,7 +1676,7 @@ mod tests {
let full_req = Request::Headers(req.clone());
let res = HeadersResponse {
headers: vec![
::ethcore::encoded::Header::new(::rlp::encode(&Header::default()).into_vec())
::ethcore::encoded::Header::new(::rlp::encode(&Header::default()))
]
};
let full_res = Response::Headers(res.clone());

View File

@@ -13,9 +13,9 @@ ethcore-network-devp2p = { path = "../../util/network-devp2p" }
ethereum-types = "0.4"
log = "0.4"
parking_lot = "0.6"
ethabi = "5.1.2"
ethabi-derive = "5.1.3"
ethabi-contract = "5.1.1"
ethabi = "6.0"
ethabi-derive = "6.0"
ethabi-contract = "6.0"
lru-cache = "0.1"
[dev-dependencies]

View File

@@ -44,16 +44,16 @@ use parking_lot::Mutex;
use ethcore::client::{BlockChainClient, BlockId};
use ethereum_types::{H256, Address};
use ethabi::FunctionOutputDecoder;
use network::{ConnectionFilter, ConnectionDirection};
use devp2p::NodeId;
use_contract!(peer_set, "PeerSet", "res/peer_set.json");
use_contract!(peer_set, "res/peer_set.json");
const MAX_CACHE_SIZE: usize = 4096;
/// Connection filter that uses a contract to manage permissions.
pub struct NodeFilter {
contract: peer_set::PeerSet,
client: Weak<BlockChainClient>,
contract_address: Address,
permission_cache: Mutex<LruCache<(H256, NodeId), bool>>,
@@ -63,7 +63,6 @@ impl NodeFilter {
/// Create a new instance. Accepts a contract address.
pub fn new(client: Weak<BlockChainClient>, contract_address: Address) -> NodeFilter {
NodeFilter {
contract: peer_set::PeerSet::default(),
client,
contract_address,
permission_cache: Mutex::new(LruCache::new(MAX_CACHE_SIZE)),
@@ -96,9 +95,9 @@ impl ConnectionFilter for NodeFilter {
let id_low = H256::from_slice(&connecting_id[0..32]);
let id_high = H256::from_slice(&connecting_id[32..64]);
let allowed = self.contract.functions()
.connection_allowed()
.call(own_low, own_high, id_low, id_high, &|data| client.call_contract(BlockId::Latest, address, data))
let (data, decoder) = peer_set::functions::connection_allowed::call(own_low, own_high, id_low, id_high);
let allowed = client.call_contract(BlockId::Latest, address, data)
.and_then(|value| decoder.decode(&value).map_err(|e| e.to_string()))
.unwrap_or_else(|e| {
debug!("Error callling peer set contract: {:?}", e);
false

View File

@@ -7,12 +7,12 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
error-chain = { version = "0.12", default-features = false }
ethabi = "5.1.2"
ethabi-derive = "5.1.3"
ethabi-contract = "5.1.1"
ethabi = "6.0"
ethabi-derive = "6.0"
ethabi-contract = "6.0"
ethcore = { path = ".." }
parity-bytes = "0.1"
parity-crypto = "0.1"
parity-crypto = "0.2"
ethcore-io = { path = "../../util/io" }
ethcore-logger = { path = "../../logger" }
ethcore-miner = { path = "../../miner" }
@@ -26,10 +26,10 @@ heapsize = "0.4"
keccak-hash = "0.1.2"
log = "0.4"
parking_lot = "0.6"
patricia-trie = "0.2"
patricia-trie = "0.3.0"
patricia-trie-ethereum = { path = "../../util/patricia-trie-ethereum" }
rand = "0.3"
rlp = { version = "0.2.4", features = ["ethereum"] }
rlp = { version = "0.3.0", features = ["ethereum"] }
rlp_derive = { path = "../../util/rlp_derive" }
rustc-hex = "1.0"
serde = "1.0"

View File

@@ -125,9 +125,9 @@ impl SecretStoreEncryptor {
// send HTTP request
let method = if use_post {
Method::Post
Method::POST
} else {
Method::Get
Method::GET
};
let url = Url::from_str(&url).map_err(|e| ErrorKind::Encrypt(e.to_string()))?;

View File

@@ -89,11 +89,12 @@ use ethcore::miner::{self, Miner, MinerService, pool_client::NonceCache};
use ethcore::trace::{Tracer, VMTracer};
use rustc_hex::FromHex;
use ethkey::Password;
use ethabi::FunctionOutputDecoder;
// Source avaiable at https://github.com/parity-contracts/private-tx/blob/master/contracts/PrivateContract.sol
const DEFAULT_STUB_CONTRACT: &'static str = include_str!("../res/private.evm");
use_contract!(private, "PrivateContract", "res/private.json");
use_contract!(private_contract, "res/private.json");
/// Initialization vector length.
const INIT_VEC_LEN: usize = 16;
@@ -219,7 +220,7 @@ impl Provider where {
let private_state_hash = self.calculate_state_hash(&private_state, contract_nonce);
trace!(target: "privatetx", "Hashed effective private state for sender: {:?}", private_state_hash);
self.transactions_for_signing.write().add_transaction(private.hash(), signed_transaction, contract_validators, private_state, contract_nonce)?;
self.broadcast_private_transaction(private.hash(), private.rlp_bytes().into_vec());
self.broadcast_private_transaction(private.hash(), private.rlp_bytes());
Ok(Receipt {
hash: tx_hash,
contract_address: Some(contract),
@@ -258,13 +259,13 @@ impl Provider where {
match transaction.validator_account {
None => {
trace!(target: "privatetx", "Propagating transaction further");
self.broadcast_private_transaction(private_hash, transaction.private_transaction.rlp_bytes().into_vec());
self.broadcast_private_transaction(private_hash, transaction.private_transaction.rlp_bytes());
return Ok(());
}
Some(validator_account) => {
if !self.validator_accounts.contains(&validator_account) {
trace!(target: "privatetx", "Propagating transaction further");
self.broadcast_private_transaction(private_hash, transaction.private_transaction.rlp_bytes().into_vec());
self.broadcast_private_transaction(private_hash, transaction.private_transaction.rlp_bytes());
return Ok(());
}
let tx_action = transaction.transaction.action.clone();
@@ -290,7 +291,7 @@ impl Provider where {
let signed_state = signed_state.expect("Error was checked before");
let signed_private_transaction = SignedPrivateTransaction::new(private_hash, signed_state, None);
trace!(target: "privatetx", "Sending signature for private transaction: {:?}", signed_private_transaction);
self.broadcast_signed_private_transaction(signed_private_transaction.hash(), signed_private_transaction.rlp_bytes().into_vec());
self.broadcast_signed_private_transaction(signed_private_transaction.hash(), signed_private_transaction.rlp_bytes());
} else {
bail!("Incorrect type of action for the transaction");
}
@@ -315,7 +316,7 @@ impl Provider where {
let desc = match self.transactions_for_signing.read().get(&private_hash) {
None => {
// Not our transaction, broadcast further to peers
self.broadcast_signed_private_transaction(signed_tx.hash(), signed_tx.rlp_bytes().into_vec());
self.broadcast_signed_private_transaction(signed_tx.hash(), signed_tx.rlp_bytes());
return Ok(());
},
Some(desc) => desc,
@@ -425,31 +426,23 @@ impl Provider where {
}
fn get_decrypted_state(&self, address: &Address, block: BlockId) -> Result<Bytes, Error> {
let contract = private::PrivateContract::default();
let state = contract.functions()
.state()
.call(&|data| self.client.call_contract(block, *address, data))
.map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?;
let (data, decoder) = private_contract::functions::state::call();
let value = self.client.call_contract(block, *address, data)?;
let state = decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?;
self.decrypt(address, &state)
}
fn get_decrypted_code(&self, address: &Address, block: BlockId) -> Result<Bytes, Error> {
let contract = private::PrivateContract::default();
let code = contract.functions()
.code()
.call(&|data| self.client.call_contract(block, *address, data))
.map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?;
self.decrypt(address, &code)
let (data, decoder) = private_contract::functions::code::call();
let value = self.client.call_contract(block, *address, data)?;
let state = decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?;
self.decrypt(address, &state)
}
pub fn get_contract_nonce(&self, address: &Address, block: BlockId) -> Result<U256, Error> {
let contract = private::PrivateContract::default();
Ok(contract.functions()
.nonce()
.call(&|data| self.client.call_contract(block, *address, data))
.map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?)
let (data, decoder) = private_contract::functions::nonce::call();
let value = self.client.call_contract(block, *address, data)?;
decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)).into())
}
fn snapshot_to_storage(raw: Bytes) -> HashMap<H256, H256> {
@@ -524,13 +517,11 @@ impl Provider where {
fn generate_constructor(validators: &[Address], code: Bytes, storage: Bytes) -> Bytes {
let constructor_code = DEFAULT_STUB_CONTRACT.from_hex().expect("Default contract code is valid");
let private = private::PrivateContract::default();
private.constructor(constructor_code, validators.iter().map(|a| *a).collect::<Vec<Address>>(), code, storage)
private_contract::constructor(constructor_code, validators.iter().map(|a| *a).collect::<Vec<Address>>(), code, storage)
}
fn generate_set_state_call(signatures: &[Signature], storage: Bytes) -> Bytes {
let private = private::PrivateContract::default();
private.functions().set_state().input(
private_contract::functions::set_state::encode_input(
storage,
signatures.iter().map(|s| {
let mut v: [u8; 32] = [0; 32];
@@ -604,11 +595,9 @@ impl Provider where {
/// Returns private validators for a contract.
pub fn get_validators(&self, block: BlockId, address: &Address) -> Result<Vec<Address>, Error> {
let contract = private::PrivateContract::default();
Ok(contract.functions()
.get_validators()
.call(&|data| self.client.call_contract(block, *address, data))
.map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?)
let (data, decoder) = private_contract::functions::get_validators::call();
let value = self.client.call_contract(block, *address, data)?;
decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)).into())
}
}

View File

@@ -0,0 +1,80 @@
{
"name": "Callisto",
"dataDir": "callisto",
"engine": {
"Ethash": {
"params": {
"minimumDifficulty": "0x020000",
"difficultyBoundDivisor": "0x0800",
"durationLimit": "0x0d",
"blockReward": "0x16c4abbebea0100000",
"homesteadTransition": 0,
"blockRewardContractCode": "0x6080604052600436106100405763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663f91c28988114610045575b600080fd5b34801561005157600080fd5b50610071602460048035828101929082013591813591820191013561010a565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156100b557818101518382015260200161009d565b50505050905001838103825284818151815260200191508051906020019060200280838360005b838110156100f45781810151838201526020016100dc565b5050505090500194505050505060405180910390f35b606080808060008080803373fffffffffffffffffffffffffffffffffffffffe1461013457600080fd5b8a891461014057600080fd5b604080516003808252608082019092529060208201606080388339505060408051600380825260808201909252929850905060208201606080388339019050509450733c06f218ce6dd8e2c535a8925a2edf81674984d98660018151811015156101a657fe5b73ffffffffffffffffffffffffffffffffffffffff9092166020928302909101909101528451680340aad21b3b70000090869060019081106101e457fe5b6020908102909101015285517374682fc32007af0b6118f259cbe7bccc21641600908790600290811061021357fe5b73ffffffffffffffffffffffffffffffffffffffff909216602092830290910190910152845168068155a43676e00000908690600290811061025157fe5b60209081029091010152600093505b8a8410156103ce5789898581811061027457fe5b9050602002013561ffff1661ffff16600014156103235767b6255df5f50080006000198c01026816c4abbebea01000000192508b8b858181106102b357fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff168660008151811015156102df57fe5b73ffffffffffffffffffffffffffffffffffffffff909216602092830290910190910152845183908690600090811061031457fe5b602090810290910101526103c3565b60648a8a8681811061033157fe5b9050602002013561ffff1661ffff161015156103c35760648a8a8681811061035557fe5b9050602002013561ffff1603915060038260080361ffff166816c4abbebea0100000029060020a900490506103b4868d8d87818110151561039257fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff166103e0565b95506103c085826104b7565b94505b600190930192610260565b50939a92995091975050505050505050565b60608060008451600101604051908082528060200260200182016040528015610413578160200160208202803883390190505b509150600090505b845181101561047657848181518110151561043257fe5b90602001906020020151828281518110151561044a57fe5b73ffffffffffffffffffffffffffffffffffffffff90921660209283029091019091015260010161041b565b8382600184510381518110151561048957fe5b73ffffffffffffffffffffffffffffffffffffffff9290921660209283029190910190910152509392505050565b606080600084516001016040519080825280602002602001820160405280156104ea578160200160208202803883390190505b509150600090505b845181101561053357848181518110151561050957fe5b90602001906020020151828281518110151561052157fe5b602090810290910101526001016104f2565b8382600184510381518110151561054657fe5b60209081029190910101525093925050505600a165627a7a7230582056d78ee4f7397a0950a3692a9e267500e619b5d3eb5937b9142689bc9ee137f10029",
"eip100bTransition": 20,
"difficultyBombDelays": {
"20": 3000000
}
}
}
},
"params": {
"gasLimitBoundDivisor": "0x0400",
"registrar": "0x0000000000000000000000000000000000000000",
"accountStartNonce": "0x00",
"maximumExtraDataSize": "0x20",
"minGasLimit": "0x1388",
"networkID": "0x1",
"chainID": "0x0334",
"maxCodeSize": 24576,
"maxCodeSizeTransition": 10,
"eip150Transition": 0,
"eip160Transition": 10,
"eip161abcTransition": 10,
"eip161dTransition": 10,
"eip155Transition": 10,
"eip98Transition": "0xffffffffffffffff",
"eip140Transition": 20,
"eip211Transition": 20,
"eip214Transition": 20,
"eip658Transition": 20
},
"genesis": {
"seal": {
"ethereum": {
"nonce": "0x0000000000000000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
},
"difficulty": "0x080000",
"author": "0xc3F70b10CE5EC4aA47ce44Eb0B7900A883cd45Dd",
"timestamp": "0x5a939845",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x0000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x09eb100",
"stateRoot": "0x2255c10db0a0f392ca63b1a3ca149e226f6bbf195c04a6ce4a077f9f02ffbace"
},
"nodes": [
"enode://ab0d9fe81f23653c3217303d3a4bc035be908b05f8b12d6f155ab4598d7760cfea1e009e414771279c9ffc3499950283afaabe099a5329c5a6013f57d77de0a6@104.236.96.118:30303",
"enode://9e2d9dc2639e02893aa17c80e6ba8e8803fd3166083b622a841fc852161112720281514436f7605c89041d5efa1738215185c4c4024ff812b0f500c403cc0ab1@206.189.47.198:30303",
"enode://149ba679e8851c3e0d030e0dc0336984b97c83ef649e68ec113dcf266449364cc1ec8ee27950f71b00c2182ef504894fa7bff19f6741978ced67e9e4b6536d2a@206.189.45.31:30303",
"enode://eeb3b1680f651b291a19454345721b5196a2a689dcd280e5f66dc3207636366d4b25e84d205303c2f8aa0a38467dad9e6f2536e195a4760df56aeac428ebea0b@199.247.18.157:30303",
"enode://eeb3b1680f651b291a19454345721b5196a2a689dcd280e5f66dc3207636366d4b25e84d205303c2f8aa0a38467dad9e6f2536e195a4760df56aeac428ebea0b@199.247.18.157:30303",
"enode://c21418c02f5ba480d64fbdf3dd7e1a276cbea441f9d55b8bb1c653fa3a05cc07e32a332f63df53f51d275dadc9b50925375a699dd39bdad991594326d6b8afab@199.247.3.3:30303",
"enode://40aa8ff2c3d98ffc12004cb6a3636e7c9b79400153667163cfc24123f2ee3ee693ac45775183f5f6a7e315a4884899ac32ef0616e26cdd23a7b00f80d07cdeae@45.32.126.82:30303",
"enode://3beb80913887d985a857076621baca66ea27b62ff159c5a41243d02a8614f537003c03ba1fe082b63a47e7f6f7ba1caf6bb14343560dbff6ba1e456e99e6119d@144.202.73.111:30303",
"enode://b79a50393b16b76a6c94d7ddae80c44464c9e5ecc59fc2b7e83d0c248190de781e7e2aebeab8d466b3869677e6388e6fac8bd36f3925cbeebbe4cf0372a7eac1@207.148.31.238:30303"
],
"accounts": {
"0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
"0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
"0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
"0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
"0000000000000000000000000000000000000005": { "balance": "1", "builtin": { "name": "modexp", "activate_at": 20, "pricing": { "modexp": { "divisor": 20 } } } },
"0000000000000000000000000000000000000006": { "balance": "1", "builtin": { "name": "alt_bn128_add", "activate_at": 20, "pricing": { "linear": { "base": 500, "word": 0 } } } },
"0000000000000000000000000000000000000007": { "balance": "1", "builtin": { "name": "alt_bn128_mul", "activate_at": 20, "pricing": { "linear": { "base": 40000, "word": 0 } } } },
"0000000000000000000000000000000000000008": { "balance": "1", "builtin": { "name": "alt_bn128_pairing", "activate_at": 20, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } },
"183394f52b2c8c034835edba3bcececa6f60b5a8": {
"balance": "100491852286952719463755404"
}
}
}

View File

@@ -58,9 +58,9 @@
"0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
"0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
"0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
"0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 100 } } } },
"0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 20 } } } },
"0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0x00", "pricing": { "linear": { "base": 500, "word": 0 } } } },
"0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x00", "pricing": { "linear": { "base": 2000, "word": 0 } } } },
"0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x00", "pricing": { "linear": { "base": 40000, "word": 0 } } } },
"0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x00", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }
}
}

View File

@@ -177,8 +177,8 @@
"stateRoot": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544"
},
"hardcodedSync": {
"header": "f90206a0391c42ff4f047145a6b9a14179c3cc404b31d92f30693e28cf2bba41f47f6329a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794b2930b35844a230f00e51431acae96fe543a0347a0fb280d4457e60a0b96577e1dde9e00905102cfd36def5c5b31dcc2284636136ea077f739c324e35c7448b14aa02186973d3c74cc1ab081498cd0c487a604873723a0e462d76b5204d14b13d1f1b39ea048a3b637f91d42c729c367d5bbdbd0a72d70b90100008003410402005000200009400030c40490500208480008414000a40048806408000080802008204400010001800c0020080c0a00400105a9080820400900240000084012030a1504030508000200005c4404a0c3490820000010400811040004708a1006910211444040c28001a800e920d00000940c200119111a10401001008044214002002080c21081801e008a320848a204400042400898004004010028840181106210080254a081112480031000410202440092c880be3894000120050500860880000108000c0080009e0000204007212840808cb80200601024020000210280100c018540b28a1041a62400000108204084000008808040000004870bc009a1914d7f8362f801837a121d8379ee5a845bbd53ca8573696e6731a0abce0f90ce69f740080eeb94d1cb13981fafe3bc6d020a44815acd86cbd3fc0a889501b04c0614e053",
"totalDifficulty": "7128515864594819065361",
"header": "f90210a0b5950d9087e0e1d3dfc18cae9388fc798d9b3932a6efb4fc073081f5561adc8da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794829bd824b016326a401d083b33d092293333a830a00caa3307575bbbe59bb8f8a89f115ccb864866c2591d8d3ec3bffa6231532e52a024278597d4fddf58a4b55fe6a8bb7bf0e6cf1c6e75158b3d0d0b1bb9bb16647da01ba199a450390854e88ea5504144be61dd681e805aed7a1cc8bea61d5b61194bb901001902100820000000020110010418b02612064240040a4051001001a0024400e2484001141a422e56073887504031028220080010040501800000080080268040050018400100cc4710800419088000005a840a201c09011040086001260040000021004842021800024204400204a8a1180a8a0002164400202000115420602005512a20410088002248c000020e801803c051202030000420810912000401010604000801543084004414c051048082100000221684005c8015a40100040170025040132500014054900482500403088004000821194124a0b20000200229b9601c230180400802020800000408e49314200190121404002080218814a08085870ac84878814c3083662001837a2147837a050f845be9e82d8fe4b883e5bda9e7a59ee4bb99e9b1bca05714f772f5e2fa3a41a8c7435407b579b7c16397cf08eca605eadd9e63db7f6a88315d0b500d2cb0a8",
"totalDifficulty": "7772265011609637471285",
"CHTs": [
"0x0eb474b7721727204978e92e27d31cddff56471911e424a4c8271c35f9c982cc",
"0xe10e94515fb5ffb7ffa9bf50db4a959b3f50c2ff75e0b8bd5f5e038749e52a11",
@@ -3346,7 +3346,108 @@
"0xae4a71712cc96a5b30b45e3b92c339c2e975e4ed683f4d1fcadcdc121ff7c6bf",
"0x226f6d8c71ec32c5eaab6b01c0fc1d00ae95e60b383d09560e90549b79eb1447",
"0xf3dec779841c9384df93bcefbba8700a292b570b29d286a7c9c5a442b4788a20",
"0x63ef48e80efa45383857adcb0f31076393260cbad058d1938345ad13faae50b4"
"0x63ef48e80efa45383857adcb0f31076393260cbad058d1938345ad13faae50b4",
"0x7ba213077278bd01ff874e760c3a0bfd4e5cf65bb18eed8b0f8076d81e16d05b",
"0x92eace1cff535745aae658d9ad90c372d41ce318a20716ae3b2c0958bdb48b33",
"0x76b2607fae8dbe532d8516c4c33e309f2c0a963bb68035f4361a2859d62d2daf",
"0xfb0c46a588438f4f217e183ef7772b649b5a45a318253496b01676253dedb568",
"0xd6dba12c700a0c5ca59b9d17f628066405de8e4399f92472cccce2e25e70ba4d",
"0x2390984444cbc9de301adaf0853f4f6ed2fb56fefeabce717306cf1e40da9618",
"0xa6992b0db82c50ce623febc7f16c8a316ce262255de11ad1914316b3d986fe66",
"0x96787cf8e0a70ffe5b84151ae8219362ba6d9465223c23c135590fe4cb9ab592",
"0x0b4e7fba24f6bed3790b8fc289e2715d9a3f4235c9316dd9d4f889f710a65ae4",
"0x49585a7af98ad032371df01c458fab933ac399ff4d2d35731a2d86fc136b5eb8",
"0x517947f22d8d56466dbb496f3e98fcd01864176af19be2112f2260e55bddbd58",
"0xbc0aa38cbc79c3557fa81e446071e6d531989d088c6311060bff971e430fa36b",
"0x5a0a88750db7ad3190dcaaf5bde2649e6fd99cc5b05979fff84ae689ed47b51b",
"0x9ad902d6abe59faabfa5fde485c2fe16f6f3e2c41aa8bdaba021e94a3c292dc8",
"0xbd6e7bf8b466940b9f619e3f433fb68c68d344974798996e454c925e2628b1b2",
"0x112b5e9d438eb79aa9d7b4488b6aa9f7edf7599dce805d8781510302da45e9a2",
"0x881255ae2cab543ee6b429e1b201c197cb35051d53f881cb51fc58f9c760e51d",
"0xcf56a4ed6b771e4905e6ba888390526eba8ba3483ead7585dee00c0eaea58cbc",
"0x12705d1609ee34bce0c82bab9da730452db57863371f5b84de84c4c135537237",
"0xa9abc081a75bfcde86ea830483be240cb3bcfa72ae34a16dfc35cb964dd7a457",
"0x65cf0c91f8567d8567ac3f00ddc19da0b916179266c7e42768fd5d7271e91092",
"0x07f15ccc91a47edfe9b67a79d05ed1da1410e3ac16e4a4c2147c3ef0de26ae62",
"0xb44eb7db9e4dbe8901bfac43ad54ef27576a3ac0c78218138715e03b3f9a782e",
"0x9ef66d20aeccdea66ade0fe8ccc0a85dbe9498305509c8919b670ae8e854a450",
"0xb10a7dbd4857f910ae8cca5d1b7a85923adaad65c4b00d1255813efef00c646f",
"0x20410bc64b58a1c221f7b38f293700591692c73a785d94a5548b336bd5db10da",
"0xed7176f398eb75ae6c1d4348d3882aade99573f8369ef00e809b1ff91b5a9191",
"0x35f06785e1f7e362682e969586322b1588624f6025692ca87db21cb199c382f4",
"0x9a6b06141660e2bd106f6d46afd2f3e64d72711ffe6a9c495887bc3932f7934e",
"0xd64e602a976e86d3948d0f4cf0b8f13a63558d5bdea5affb36eeb91007a653b3",
"0x71050553ca1da7234764a5486e4647fdad00652560eb47102c1d0fc039b4b63e",
"0x53ba43f79de58a957e8ac0d998ecb4999c68f423b1769d9e8df2405259dcdaa6",
"0x17b33d269609bd90fac57eaeb298bf489a3b8a985cfd9998d297c7e0628bc84c",
"0x9b47bba7ff6b283e76100e36246c0dcad836ff29a674fbb1c6d2f58e38e29f92",
"0x262f8387628500fa26e2cdca6b5938262c8fa81888daed41a09d880df136167f",
"0xb6c6d0ed2824a9818fa9476c99a810cf33a0c1fd3f2fb6b7a44603f2442525e7",
"0x6f3437e677dcc60cb587f6100eaa2e7ef5c76b57023b63ae61a6a8ed2750512d",
"0x4bb5aad759b0c6390cf4dbc6c32e78f2721c2be3f40ca3d11de880fbe90e456a",
"0xfbeced3e048769a07bfd50010de59cd24f2c534234abc1ee7f3fe9d7e3d9f482",
"0xbe871fdd431974370e8156fb9347377d1bb07990ff60296abbaaf2c38b4059d0",
"0xcbdf566fceb5adc33608a847c77b6f3501cdc4182ba98e04e1f7e8b8ae66ba5b",
"0xa06a5de4aeafdb5981ae02004a38c524116ebe557dda83abdf03141e4dfbd4cd",
"0x73660bb361b94287b85b6c41394bea5447e8e3ccffaba1772a765a8fc0fa9b27",
"0xf80439908d6173fe4fea42aeb07ddea2c644e581373dbe9dbb9d092f12fd2125",
"0x32d935f078bdbb9ae693bef4ab8316e7da701edf42f156568b639193b0ea24bf",
"0x8ef0b9f247b5b9d9e5a813877d03a518d1f06900e2fdf5743feda3537ab3777d",
"0x59f92f14340a77b94839b6ea61389691a6fa5bb2ddc5b2241e873b066d37fc61",
"0x0288bdae302901b701df46263f4b12bdd6bd76436c3ae1626936e1b4bb631ca7",
"0x2fcfd5a54d6bbe07d4063ef64fe4b164bd8cb89a8e03cb5fabee98bfef280e43",
"0xd8d1169b3a9aca48f167cd43e9617d3ecc74658ea61ace251beb370d3c05f86c",
"0xdb2c3ef7b8a8a18ad3a8ce7cb8a6be2e1ef2cd694fb3f1b2e0732f2e27c758cb",
"0xfbffbf26f4756bcf1cd217686597ffe9c1282a70b279c8b01ee5076ec31b1c2c",
"0x2cf1404cc8482698eccde40185740753c47319b1aa30d9204fe53922feaae9b8",
"0x553a9e079d09d3f8251947ab37891027fc3d041246f2e43f01321fc3523b508f",
"0x35954f131f276933c7ef3938f35c6011806c7dd637fa249451379003d740cbaa",
"0x1ee7a658e8a2368391810667c35b8b0e321d381907e2312e7789a3cc7b0341aa",
"0x4cb3c908526bc6ccbdd39d855b3b3649e59eec4322bf48f07598d98240101d0c",
"0x996eb99b0cb27fb5ec07873af17933f377ed2c131f02926bab74341c475a95a9",
"0x68a90de2c8ea439db0417b77a23eb66e7421268335be7e4f593a52b1093681fa",
"0x4325afa26bf545951a73c016d866f1c71a5855ef52202b7ad0c54dc23906936d",
"0xaf5111b606b0e6d699bb4fb61c8a0592af7eb45dd7357b3e896ebc3e798919ad",
"0x4de03498b2d532a8eb01a12edea2a15b8a907d6d23ccfc380507a5d294abce99",
"0x5d642ba55dc046ef1b84fe594ae2e46b844cc6590d580e2591ba9c0c1c942c24",
"0x8477bb69d6d23ae4f45e56c372d66f42ba7417cf5107136081b5ccdd208b1545",
"0x924f641a7cea7cf76ad8920b9ee7c39e74304169571b028fbe40e6ed255a90f4",
"0x4b39dbfae8635f286284009a0213c6d267d5f48485a25f2df855c5cac5e7d6ca",
"0x61827bf3a120a079111665f78ba2e5ad15943492e4ffdfc708e235f44ce92842",
"0xdc0c0dafc340277058a6f8e03bf4e5e733e05fa638e2a8c4ebe4521960bbdc20",
"0x7038c52c4e92d6ed20b19481ed63d432325f94ee2a3ad4c0d5e25fafe5b32bd6",
"0xe1f5a1123679ce45005d53672018e16648fd44c4a2251802f295d29ed876a0db",
"0x173a332438a181f6cf1773b2603556d229254861534f34ad65b2170b0cf47fb5",
"0x22a19ab1d828b5d05057f40f5cf798e27ec068fc584968987b7bbe440f52ac84",
"0x15b3e3b6e1de6b8a407ad7e325c53c4bfa9e73f23c6f3acedcdf68d759f73860",
"0x0347a8e310cbc921daf829002ba0c44399c4dd7c930ac1fca203272949e09dc9",
"0x9babeec2d3003ddb15fdcb89ec7b61c0d7f795145b58f55a17810447d5afe5be",
"0x62c14ff2ed414ede1e3fa7fc2fccbab0b8f284b9f38127823c3dc9eb55a08b44",
"0xb301a7c865abe0f42d9444b5c3b775dc6ab4c99effbe8d54cec29745ff4af01d",
"0x3fabed16363d78f34a13ca6b99cfc592671668d4281c5eb3ab07f4b9017a4ebc",
"0xb14af7c7331f7b5518e04bc31c8c2b63d9d497acac405bc22e1ab2431105b867",
"0xb7b90e8852ae132f858cb98635fd6e1267b141de7da6773ec4092d5c83def42b",
"0x1a5c8bed811fc72de8146516cc4d668fc4557baf48082503a2a5cc0e473b6e08",
"0x0060158b427095081a18fc57c4f56290873188960dc0e4d2b16cdd57b5761100",
"0x2f0dd546f4982d47b6e04ce282b19be8e165b5c89b5f03c1ac8c6d8be2af2b4f",
"0x229d31a50f46afeda23a2535c8b011a827383c981e7e59f67622359e4b307a10",
"0x10da7b2e78954845b506b9672ff93d3a617f187521116d442b364a1178f10f08",
"0x511325c034c772ff3a61b1c8d94e3c13f19cf1e93523a8924666833bc1e5b0ba",
"0x3a8b0251b2f7c99774d0a7863388422723b5405fd1db035ec5e30df90306e251",
"0x885c3b0507dcdd6e1cec187cf3d97ee12ce101ccf63d99c1c7fc77dd57ee0439",
"0xa76f1fdcf546ccb62f86ec7b85bd8eb662f696d7aed2f2ed2b3c769af90897b2",
"0xbec073b15a35de54487b60f92615cd44dbcb5a5fa9d1bcca2ea31437b2e45756",
"0x662013eba4201630ccc4a9b6fb1dac36f439cc6cd2b6f295c0260713d075108e",
"0x81b0148f7e690088330650b01c52831d50f3d30ba2fd2074bca5513c179ad30a",
"0x01614cb8f2f2bd6794a20513fffe99a36eee526b7145405db15f9c2ede980093",
"0xd3d8664a5464c8f681e37265948c4046e373843e602bee66c8583277397db258",
"0xdaf61a9e7157100cce6ea5bc405926fd4190fda7354edaafad9b6e468bb24422",
"0xeb05144e032621f7b1792dacbdc79c044a268442a9a9284ef1b2d1d60cadb29f",
"0xb1916e802e8e3eca2570d1a190d317cf38cf9f6b58119b65ed0d60b9749461ad",
"0x17e103cb26e7c5c7678a523f99f90387490bcca00916190e7e1b38274c52a375",
"0x105b8126ef037364f46a44fdca4fea1ec4c099de5a05918688249fb8844dfea0",
"0x7ca09f536bb9f0d7b3809c086918ba4750722edfd47153a8412fc761eb4783c8",
"0xc988cc2d92dcb85eaff8cf2f70ca49646cc5aff6c8e10b43a0581193137d3b92"
]
},
"nodes": [
@@ -3377,7 +3478,9 @@
"enode://cadc6e573b6bc2a9128f2f635ac0db3353e360b56deef239e9be7e7fce039502e0ec670b595f6288c0d2116812516ad6b6ff8d5728ff45eba176989e40dead1e@37.128.191.230:30303",
"enode://595a9a06f8b9bc9835c8723b6a82105aea5d55c66b029b6d44f229d6d135ac3ecdd3e9309360a961ea39d7bee7bac5d03564077a4e08823acc723370aace65ec@46.20.235.22:30303",
"enode://029178d6d6f9f8026fc0bc17d5d1401aac76ec9d86633bba2320b5eed7b312980c0a210b74b20c4f9a8b0b2bf884b111fa9ea5c5f916bb9bbc0e0c8640a0f56c@216.158.85.185:30303",
"enode://fdd1b9bb613cfbc200bba17ce199a9490edc752a833f88d4134bf52bb0d858aa5524cb3ec9366c7a4ef4637754b8b15b5dc913e4ed9fdb6022f7512d7b63f181@212.47.247.103:30303"
"enode://fdd1b9bb613cfbc200bba17ce199a9490edc752a833f88d4134bf52bb0d858aa5524cb3ec9366c7a4ef4637754b8b15b5dc913e4ed9fdb6022f7512d7b63f181@212.47.247.103:30303",
"enode://cc26c9671dffd3ee8388a7c8c5b601ae9fe75fc0a85cedb72d2dd733d5916fad1d4f0dcbebad5f9518b39cc1f96ba214ab36a7fa5103aaf17294af92a89f227b@52.79.241.155:30303",
"enode://140872ce4eee37177fbb7a3c3aa4aaebe3f30bdbf814dd112f6c364fc2e325ba2b6a942f7296677adcdf753c33170cb4999d2573b5ff7197b4c1868f25727e45@52.78.149.82:30303"
],
"accounts": {
"0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },

View File

@@ -62,8 +62,8 @@
"gasLimit": "0x5B8D80"
},
"hardcodedSync": {
"header": "f90247a01865856fb6e4118598117560df31734c74cf725c8edae4db941055ac0afeb207a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479400e6d2b931f55a3f1701c7389d592a7778897879a054563efd593e9682943065880710af9187131127148575efc8bb51d80dfed41aa0a568a1653a6c7d559711be0b91a8e75db76c678dbdd286c75b88e4f0c0d31171a0dab32c5cbe9b9244a7af00afa7f6042a4ac923573e8f2f025b107abe1e3da999b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000004000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffd8389b001837a120083046540845bbd803c9fde830200048f5061726974792d457468657265756d86312e32382e30826c698416ef600fb841387b51dae8bc8daa6cde190d3f44797690b4da1ce5fcfcd54bdbb2a6ee6d8c1f7649081ca28b5cd70067ee9f61e27d8184db83705102d5e1a269f2b631b4d5db01",
"totalDifficulty": "3020091077015059097853315484608800838133866777",
"header": "f90247a0434ba1ebe3bc9d9d12886f616afee0eb785dd00d78aa64502045b249c8a3cc33a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940010f94b296a852aaac52ea6c5ac72e03afd032da0d1c1137be913218840c44bdb8f5709a59d8608b05be0dc2401402e11ff1bf2ada0eb50a864e57e19bd4c8499725a6a3841f706ff5d743e64f1d06db903aca62eaba0d4d77727f7253c109e6f048fa5b1583b6c2911ad77f7d59d8947d38a96a67729b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffe838ee001837a120083013502845bea4f689fde830200088f5061726974792d457468657265756d86312e32392e30826c698416fa93dab841c80b3e34bacdc91e01f6a76c64a920a65edfea86b84e0fd59c6d8dbd7758f2dc4e3cb446de8dc07f3d8cb71375a6315f401cd1ce54c56694e4e01f7e774555e701",
"totalDifficulty": "3135776192732436705400032023148164213445066062",
"CHTs": [
"0xdb9557458495268ddd69409fc1f66631ed5ff9bf6c479be6eabe5d83a460acac",
"0xd413800c22172be6e0b7a36348c90098955991f119ddad32c5b928e8db4deb02",
@@ -4470,7 +4470,173 @@
"0xbe48c727fb6a32242229eaa09146c76522dcf6bed6d1c6fc1bebf86b5e4ccdb4",
"0x8487b971e383272df82cd812a0bf3a2026b85bc3897b4ce9ce48afa00849fe00",
"0x60d18b465172f59c0d71594b5273a90cb41db24a5d4c9fc37020f9d8c467a4a2",
"0xab4e36d9f17c748c87d89c23b667e3f4e3265e77b62dbd9c92659026f8a53d12"
"0xab4e36d9f17c748c87d89c23b667e3f4e3265e77b62dbd9c92659026f8a53d12",
"0x2c711e8eec1be3caef6e16a03dcca83dac3a565c93327c67f4e8ea9f2697d9e9",
"0x21d7a9a3f22a163767075aa693d82a962e4458b074bd8f3485c4ded1e47c1172",
"0x1509cac83867db4b888107974d5c8547dc4aa1db3b8e886291f0f9eb6bd7af58",
"0xa555eb6001982080479c9bdd3da9e8668bf90ca9538f16f27a45ae698ec85fb7",
"0x1d1f4019fa3ea7ec85ee0a411560738791f2d45fe5fe6242d07267183a852b96",
"0x2a8994caa5a27eb3081cc749cda5694da7ed3fbb8a1b4c67d7e92306cbd3c6ab",
"0x8389736ba114022ea97a6b3e755d75e74c3c370e9eb916c0f2d73a46a6f6c396",
"0x6a2e5d08ea64195a4153fc7bf26b7a99dcc9d31d8f58faa07510a1e87fb1ade4",
"0x78b66b38fd9b9cd3a5bc9c91c6f816153c2c28c1055f7ac9ad12ab61f9464850",
"0xb2f77834f7a88c4354763a28080d95be44dcb380d01f09292e679a6ed274b179",
"0x2070456b2bff0c30ae26b2435af82e153094aeea8102a75541e02a39e9ebe717",
"0x4e3bb2fbdc71602a62f0c423aa45398af09cf3ad24f0437027b4590e7056b882",
"0xe877208750e7569ce78215659ef78c1656e98b63ab6cc3e1381d7581afbea99f",
"0x8c9d8132d01b83cffd1a1fd9d19a3d2fb3a58a0a28602018db44f8b6dd5fe1aa",
"0xcece8a371b72873a660f4077f98b04d6a3cde1a150852db3a194a293e6a08b72",
"0xe72c8c7211acf2d67bf904cb3428c6fd69c8bd679d52deb3b2e749d5a3124b86",
"0x504f53693e747fbba7475dff1aad887ad0124d48cc7892ec488fda56e31e0de5",
"0xddb3ce7ac0c7e2d141df857e9e5c083d66f4a62ead742bf6631756a72fb643e3",
"0xdc1c6a45dd8308ea319671732de7578a65a025852a3cbe88aa9c5d770d662990",
"0xb6a9df772bdb5e7cdff569bb9d3078c081ed53e870f9171a5b0369d84fe6ce50",
"0x1b436a7d8c9af357c8175430e1d0d3057096c92bd8bd24fe285fa55673c68b72",
"0xa57ce7fed7521e26a908ead89253bc57939459b4c34fba583eececd0f9104e2a",
"0xb16c4f6bdce8de6657d049e2e41f91a1cef8623671eacb9ab02fff45cee7c0c3",
"0x8d23f3ea29767da41a2090cfceb56a65236a405031b69e614c78fb79c1847651",
"0x33149d4876fa24dea4e872ad1da120e01b14e8f9f8270611fced328a36df25ca",
"0x266c558486a85de2536e8849d49443e7d39797a6ed817ad7217633c28166bf06",
"0x2073a22a1f157025228f8fc82bdaff48d3cb1c9b004ac2cb867c2cbbe7cafd95",
"0xcf643d70f96101c99cedcc2d169b0196c564e7a8b235ae093ad25b1ba8981d01",
"0x1489101bebc1b60e4c0fa37a94bb946f1b51ba284c667e4b2f3270ef9d264d41",
"0xd2eceef739e2601390d872bdbb58f8d67864b000f7fbab07b0354c44279379e8",
"0xf67a02d7e7e6da127015e5137f90e30ab43c2e828e62c3f8fe68ad5a0a3011fb",
"0x01fe94220a07efc2bde2404c584f67e9b06e47eba05e50e71ad59710d9d6a9fd",
"0x509bc80d1a464116b4f234001c3f2d7aac7772cd6ec5fa6ef9606ab8ab273127",
"0xea497db1233691b3b86d8fc80ebffe28e6863f445a0b352a1286412a94ad2f6f",
"0x80074f0e2cb668b6a8e5b454db4ae5cf2482894f3ccb7648cfa26b3365a0a54b",
"0x56c8cd15e5e1a21c6f32f7211d18e1e56c89da688cf11b80c9e55718514eab24",
"0x6705989758f03a8c4ee93d44f53b4114a10337694197186b62ac2220188a6879",
"0x7581fbe2b0ae6e0a61d073fd1700c3111d2e3e8d9342d50800ba05d026c9edd6",
"0x254548091369ad8e0abbd2eb4e31e2c08c8e9dc0256fd0097e50e75831946924",
"0xac3119a5ba40f303a9a70ecdef9b6d4722c6adb6592a0cf52e5a312a1a0819c2",
"0xbdf30bc3cd852b882c5d410e6d4419e0f36ed17b761b58fe58ded980829d1cf8",
"0xebaeb5965563f6fa71006d8c2d285e093a167630c319cee2dfa961c4a583b60b",
"0x6cd6717885bd50263a97574e8a56a3ccbca88229bce595b38a454c1184ea94d5",
"0xc9bba3a4a72f0f08663e3af36e2bac2d4c8422b2e3c3bd29705e5b86e7c42a20",
"0xcc442230a4b6aed5a1eb2b8744a09aefe3cfb9e477816edfa829dfbd3f7c2bc7",
"0x4ee48471e3326144c7a48b15fa5f39691ad9f24b82430ca281eb961b18019e02",
"0x35016779dd877530f99b1d3372a0a77eff7ae831208d2bdfcd0979b838190acd",
"0xe3e9b2a4adc4b4e167376b33b8bf2a00bd64d52f66f4e7b291ade123e8c04402",
"0x5a7d1466e2538b62ceada9577079248788e912e23c4cbc52d7b82a1afbf28ec7",
"0xb8529c5a2b2dbfb72e70165b9c9291e7c02b43f157092a9b59f3b4cad85fb587",
"0x55e90fb666a950f38ae41732269cb69afca8643b75a99bce508a16e06685fc03",
"0x651f45996ed080d8a8dcb78550089331ad67c2df33330d1871dff956463aed3e",
"0x9c6b4a961663c59dde3a4f0fdf7b68b0b5f049719ba0d10d841855cffc7ee166",
"0x15c4d98e0ee4fa1535f83625a20bf1a491852884f8fe608eae6b9bde45986779",
"0xc7891cf34fcc61935a43f37bd7f23b674c785ef3b2718358fb627364f3d8b09b",
"0x8105fb76c9e1281f0f0d7c520dc6cd1d546d1b4b29cfa398eecd7965af57f408",
"0x2a141f1c4e1f1e7be5d10c444dde3d1b5fe1a69f23506d5ed1842957375a1208",
"0x9d2313d34a5a6873f2ae1e2684db00e3b693ba962796fe7e78d26a2c49104471",
"0x84d0245b1537ec1fae89fd39741d3b6427ceda3933f750befe4e2d8ec022fc1b",
"0x93d281ff6bfefc7f94058a0d87cb826b97728c9593ef4876b88c35d26b2163bf",
"0x9018a352b09cb36311d0b54bd83a33dcd5dca5ae7032f1d399fec3a0e5a9cb7a",
"0xf01486ea17dca0bb45c245c9ba76d20d1a2f4eb718b7d07fb5183736e5cd08c5",
"0xf797fec0a8cddb31ace66223e1355211e41211c4bfd33a416c8a1a86e497f630",
"0xf24aef69daf4e2b90b4f3bdedddbabbae86a7fd1182947da7306c8145f82cc88",
"0xdd14e34cd000ddb6ae6426dcd78cabbf6bfbe5b3ecd7553c4989b3891e506257",
"0xc01ece645c7430801ee26b20ad215e221f7de0e060fe004b450b372a6c4438a9",
"0x64c836653383bcb165207b80ee8f9377ad25ef1bcd6cf7ba166cca78419898ed",
"0x6b1cdfa195df272d7e35ccd843191d5725919c0d8b71f1abf4b950a954770503",
"0xebe51f94a9f445d83180c4f075d944fa2f05b5b784b7e3cb4bc1544020bd35cf",
"0x7007f6b2c04420d390fbdb6a9fc21edd3249c1a098f8a9383131b8be50c6f975",
"0x6b7e93d96f74fc2b068104a017fa5fa74836e8be5599865309361ad9305d9bb9",
"0xcccf2dc238c68464f3b0446e06fc48fedf202e366ace5734cdac5a7fe7c43342",
"0xfec77750c277cd6bb0937d25d7f598d07cbffb1117b6232e932a296f32b45ce5",
"0xb04e6883c11ba3f2b7f0301936c3dcb622f6f78b3d3d57e48c6dcba063038d6e",
"0x23fe83ea2f197cb97a3ce5f2afd75652cae993f30bc627e8b9572a0069ae088b",
"0x44cc6bf2cee513c826ecc0c130a32b61b0153129721ad2a70d4503b71c128247",
"0xb1a11be5f9b37faf1901b1405494af32084641dc02685ec33be7f6e82e360a42",
"0x284bdf9a6aa0ac964b0f5e72d0d47c713c919d72fa9e24f42b65d749efb6e2c3",
"0x96a0a0e92ed87946a322c9bca6c0ebf70e51e0e825e2ede85b975349f9bb2caa",
"0xd73becb6a3d9a155d46a96d17412cf015724a79b166d2961d24125d92e355947",
"0xd87f142746611ce081945999f42b8da49cbda03a10bf953ba043417861e27c77",
"0x4af010485b5385579a534693bd21ef3768c8920c5b5dc6f9ddf722cc68fd6550",
"0x65a2f4ec5cf3b37530fe0672418214618393db47ad1185f285b445cf5f53cf26",
"0x1d208df2a2785599565a40d934eb2c0cc1673c1dd43d11685d698122ecf24d6f",
"0x046b7211427f0027ed4b69b06cb43986d3cd53d1579a2e078f6904a06ee6587d",
"0x053fb3ccc35edc1a1623f8652dd8c239045b02b58ffe7d51337950ae43365990",
"0x0721f82b52ff87272e1b0af5f4dc16b90dfaaaf3ba56b91bef555d283c98a8ae",
"0x26e93e4e2d0df49a857bfcede7e6ac234d75b71617b561ce39c3db130449e4fb",
"0x5ed6d53c35a0aa52d9dd0a244f31be00426292c11676737c7283f567ba485dbc",
"0x047add17bd1601a06a32b721165ecb2afb55290e025a828696f234b95c52eae3",
"0x6f9e6884745cad7091646f7767a6b17ebffb6482ee4726f5c1f3b9e02d26b77f",
"0xab29ed5be2938fb19614da621ea9828eb338514309b3d56efc6f19b57b8f4f6a",
"0xd5f14043479e8e37c6545527b2e93a76763a654661af9a25adae2b37dac40672",
"0xc43635c1489c3cf3aa231419bfcf7bcb2455a812e4781e5947bb76cf0219d1e4",
"0x72117c92f8bab83ccc7fbe5fc6cd931c765238ebd67ad8c4fcf1353eb78c8df2",
"0x5deed7df3559ed75d7c2388a6e583067222684741143350f85d236bc5fb4075f",
"0x655bbc0590587c030902e32d88cc9113fcbdd5c3371820868768abaeacecb79c",
"0x1641c875e8e44b1fa71badcbb4f724a71e2f916d9cd212f09e9039ef41b1242f",
"0x40bacdc3f0b53522cdf2aefafa2bbd9c8e9f8fd25b4b33bc19a87d72a5de293d",
"0xc35c6cffaf93170662a6f3d4a0152c988b0f4916a33d037801f6f589a6140d08",
"0xd4e37125c0ca7844e048bac4e4c6069ec24b0493e4547f53679fc8df2a1e0d66",
"0x34c6bcf0e01dd55a1d3a82df0a2edcb2caccbc4be93fdfde32c7718276e59bbd",
"0x78e50d394d9d42ca8aae3f4dfccfb32fc3923073a6643c010fd49ec3897c4fe5",
"0xeba75c237fb213e893083c5ed0e28dde3ec1f5f1b60edfdddc17a54de9cdfaf3",
"0x4f35b9a67fc66492fea331378c479eba921fe0a6f0589b5ac07a44b1ea9b4995",
"0xbb4d09d98b27d672259b608f5075575cca49f87cce0519813c1ba4a614d369ee",
"0x805550ff80be2d3a543d5076961442f70dcd86e82762149c125d2ce371a32f69",
"0x7d81d766cc2d6c66c7bf07be0a416f2a4c0dd2bd94026270a410ea6a051dd4aa",
"0x30edcef101041c0e0acecb8d6c15a28c70b8894e56196cddefb5fb6b39658ceb",
"0xe5e8d21a00ccabb5cb50b4d04ee1dcc217fb9908e72bf0efab69d4ce7a0b7eab",
"0x3793f78e2e582b56fb3d24e3bd4aa69db4741e768795f9681285b0fd34ebd602",
"0x4a9378b4ad76df084739b2a63459ac67abf8eff7499210936fb9e6644265054a",
"0x2e47b62375a267e104ad2f8bfaf5c985fa7c6f4c438739810517e41141a825bd",
"0x73dd638affe08c104b37d53e6cb7884b8a9b4cd4afa4bbec6ef608bab4559dd9",
"0xc566dce73da1cc0d069a032045c44ac4ac86b145efd2cb1c363a2d403fd8d7cd",
"0xa1a04d193c5408d0edf85e771c6976c5dc8de08c87d906b6c9de1efa4b4fcbca",
"0x3245d987f205b01c54448d9a9d76bc7e4174c1021726a68f5feb6748ac373f8d",
"0x1f963274b936dde92281f2acd47d3685261b03845efc7d10ab8b02500c239af0",
"0xa1e6d69b28aea5d24c3dc301dfb0d6df8ee8fe693d1d0f419cde3b4d20d22a89",
"0x31b0711795c77cae9e1b62b87244a5eafa4b1764aa1620d53be7e779db060984",
"0xea141234dd00c54ec7912c80baca591b53a058b81fed1673317fa4ec37c2c715",
"0xc5902f3941d647da304e94062951b09f4d6da5bcff71517c7a35e8b49c6ac569",
"0x54c5677af7e31b84010f8b2941ffed5080e9b4d18b608fcbd230f163a5e04ba5",
"0x1a12c56542a01bc58288a58e8e526f2b2c81a5238c83bbfe4808d206b3b9d0e4",
"0xa398984bab81b7640674893496b2346eaa8257aad4cc8bb52474f7162fb6fa2d",
"0xf454a592314f1b7459d21eeb6ffe54c96ae2e25a7051dab1f8129518d3788cd2",
"0x12964f85bcc410fb40e89f518d749c7dc2be7546a960849dcf560eea2ec3d333",
"0xb176775c2ff94aedef2c099b936468986874d17eb563086215525acbee2fdbd1",
"0x250de6e94d60125bb680e862fcb70823d06e4f27308ea1ecea8a465d5febc860",
"0x731cc6817fec665290d7637c67fdbc72bbebae70a13f9346f47f3b368eb1e4a5",
"0x489e955cc77f16d8aa16bada320127380315eac978f0fd1033baa04911123332",
"0xa88623d9f89221dce46b55ca7248581b4e3ace94a7cccc9fd44a3b03412fa729",
"0x4a65c1808d79577b36dfb5fa74d0deb96e90d0105ee373d552685cc4f73d35d8",
"0x7aa8228e6f8fb98a23e1599e12ecd84c879475a23f10660e763e338a347c9002",
"0xa825d02023ab76478b83a2a61dcc5cf6c05ca741b960043adba3f13d1c99612a",
"0xd3c90e414048510d9594ae7a593e25641b6baf93f9625cc4a3caade094f02e07",
"0x4d631d9024a4e75111189835b4ec0007a6951d710512dd7b91a8d56da95e57b2",
"0x0158c7f49affa675f04aa4ebdf11e88bab8c6dc0abfecc0100d32489b0d59f1a",
"0x4ec96496694ef53e17b11b3122cc45cce3a4fe1a252fe9c0d379b302db1318ac",
"0xeec44b94d9f6c7359047d257ffd5f1f5cee87b3ebd6845dc1fe48be686a9ba69",
"0xe24c7b667382186196e5da605ce75a5cd9c7e4803fb2e268b4de5848737db026",
"0x14a551850f945f02fa2ab84c6ffe3d17930c81f5b15e94ce92342c3646b8cd9a",
"0x7e9a72469a52662bbcacd449dc7df8fa75e5cd1480dac3b635148a34e0f9e375",
"0x2dd4fd0394574c5d8c9272c42175e3a88d8501753bb25a77fa937123d0c2538d",
"0x6f044eb54fd2b8e51d89f6db2ee6e654b144d9e69cddf79b7899e06af5bf39f5",
"0x091d894513fca5d2239f6b5ce73737aa2657c90c2af196b2b893ba0b0205859c",
"0x78b9ca580e3eca0808e60420ead000365eeafa60c6394e055a653a7f536c8b6d",
"0x595cfe325aa600ef0d7de6b2eb717b33c92dfbb1e3ecb9487fe332c878e9f121",
"0xe1dcc22aa44a0243f67dcb0aef7e0eb1ceee269b0faa67633698f8ee29155115",
"0xddd3354d4167161c6b18173ae24fffac2cff12a8bcb3ddf1d964907716685cb3",
"0x55c02c02eb758f8c9aab60a2432d29e73b567e3e3d0148611ce4569fa074c5d9",
"0x5d07d5a7d45fe16a0521c55b3dd898b922c619e5b938535e2f974f11b4edfdc7",
"0xf75100a1a2f8d6daf0dc36569cbf579ed6e52838b163fe50b5deaad8fe7bd07d",
"0xb6391d028fbc88825eabf1dc4566e58112e6d3b7cfe6d387d0fa58df387df78f",
"0x8a58fab34ada4d30eecbad64a001015c91e446cf14e95c9d7a3d894530787b03",
"0xac13b36d0eb0483ab8cf21f49c78f9e32092c74c878ff520ed3a3c0080fdf5fd",
"0x358c1021fbdf028ec82b811cdeb504adc2611a1ab477e8a191f780592d598361",
"0x6a7af25eb6d089ad63712187d1414e8bd04fb6bfbac26e6086b1a3e2d66f6f7e",
"0x6bebf617fe66129dc8c9dadef1a74df05567ed2fc89f4e5c4dd36327d6b0a5e5",
"0xc658d76eb9f3fb91327c64668b08d3e9bfbbb2099bf5d9aeb6a61b8e4f893c39",
"0xfe68ecc66eaa625842068f8b5ad4bdf5cbce0c82ecfafa4bf48b08de49c58595",
"0x26eba0a168f2e5f3ffcb37955839d37432b39f2f447497854d42d802826fb1ee",
"0x8b4f8964062d0f00e40a41d21852a2e22abba1f4cf75f594797e368e4df21f7d",
"0x916993123d91b181d145e2668efed6eae3845fd76d4765df3a04d8adde8c7142",
"0x21b91051b5c5fbd22164a655de8485cfc2a9eff58ed09d6fbbb454560898daed",
"0xb52ca76065bcf43f06335977ab87d6c809dcf4e6cdfc452ac2018b77c64089a5"
]
},
"accounts": {

View File

@@ -10,12 +10,7 @@
"homesteadTransition":"0x118c30",
"eip100bTransition":"0x7fffffffffffff",
"blockReward":"0x1105a0185b50a80000",
"mcip3Transition":"0x00",
"mcip3MinerReward":"0xd8d726b7177a80000",
"mcip3UbiReward":"0x2b5e3af16b1880000",
"mcip3UbiContract":"0x00efdd5883ec628983e9063c7d969fe268bbf310",
"mcip3DevReward":"0xc249fdd327780000",
"mcip3DevContract":"0x00756cf8159095948496617f5fb17ed95059f536"
"blockRewardContractCode": "0x6080604052600436106100405763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663f91c28988114610045575b600080fd5b34801561005157600080fd5b50610071602460048035828101929082013591813591820191013561010a565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156100b557818101518382015260200161009d565b50505050905001838103825284818151815260200191508051906020019060200280838360005b838110156100f45781810151838201526020016100dc565b5050505090500194505050505060405180910390f35b6060808080600080803373fffffffffffffffffffffffffffffffffffffffe1461013357600080fd5b89881461013f57600080fd5b60408051600380825260808201909252906020820160608038833950506040805160038082526080820190925292975090506020820160608038833901905050935072efdd5883ec628983e9063c7d969fe268bbf3108560018151811015156101a457fe5b73ffffffffffffffffffffffffffffffffffffffff90921660209283029091019091015283516802b5e3af16b188000090859060019081106101e257fe5b60209081029091010152845172756cf8159095948496617f5fb17ed95059f536908690600290811061021057fe5b73ffffffffffffffffffffffffffffffffffffffff909216602092830290910190910152835167c249fdd327780000908590600290811061024d57fe5b60209081029091010152600092505b898310156103b75788888481811061027057fe5b9050602002013561ffff1661ffff166000141561030c578a8a8481811061029357fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff168560008151811015156102bf57fe5b73ffffffffffffffffffffffffffffffffffffffff9092166020928302909101909101528351680d8d726b7177a8000090859060009081106102fd57fe5b602090810290910101526103ac565b606489898581811061031a57fe5b9050602002013561ffff1661ffff161015156103ac57606489898581811061033e57fe5b9050602002013561ffff1603915060038260080361ffff16681105a0185b50a80000029060020a9004905061039d858c8c86818110151561037b57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff166103c8565b94506103a9848261049f565b93505b60019092019161025c565b509299919850909650505050505050565b606080600084516001016040519080825280602002602001820160405280156103fb578160200160208202803883390190505b509150600090505b845181101561045e57848181518110151561041a57fe5b90602001906020020151828281518110151561043257fe5b73ffffffffffffffffffffffffffffffffffffffff909216602092830290910190910152600101610403565b8382600184510381518110151561047157fe5b73ffffffffffffffffffffffffffffffffffffffff9290921660209283029190910190910152509392505050565b606080600084516001016040519080825280602002602001820160405280156104d2578160200160208202803883390190505b509150600090505b845181101561051b5784818151811015156104f157fe5b90602001906020020151828281518110151561050957fe5b602090810290910101526001016104da565b8382600184510381518110151561052e57fe5b60209081029190910101525093925050505600a165627a7a72305820c9ab92a56245040e76af5fc4f3ac4cf4315336b503db06677c21aa1e00aaa8e20029"
}
}
},

View File

@@ -1,162 +0,0 @@
{
"name": "Musicoin Byzantium Test",
"dataDir": "mcip6test",
"engine": {
"Ethash": {
"params": {
"minimumDifficulty": "0x020000",
"difficultyBoundDivisor": "0x0800",
"durationLimit": "0x0d",
"homesteadTransition": "0x17",
"eip100bTransition": "0x2a",
"blockReward": "0x1105a0185b50a80000",
"mcip3Transition": "0x17",
"mcip3MinerReward": "0xd8d726b7177a80000",
"mcip3UbiReward": "0x2b5e3af16b1880000",
"mcip3UbiContract": "0x00efdd5883ec628983e9063c7d969fe268bbf310",
"mcip3DevReward": "0xc249fdd327780000",
"mcip3DevContract": "0x00756cf8159095948496617f5fb17ed95059f536",
"difficultyBombDelays": {
"0x2a": 3000000
}
}
}
},
"params": {
"gasLimitBoundDivisor": "0x0400",
"registrar": "0x5C271c4C9A67E7D73b7b3669d47504741354f21D",
"accountStartNonce": "0x00",
"maximumExtraDataSize": "0x20",
"minGasLimit": "0x1388",
"networkID": "0x76740c",
"forkBlock": "0x2b",
"forkCanonHash": "0x23c3171e864a5d513a3ef85e4cf86dac4cc36b89e5b8e63bf0ebcca68b9e43c9",
"eip150Transition": "0x2a",
"eip160Transition": "0x7fffffffffffff",
"eip161abcTransition": "0x7fffffffffffff",
"eip161dTransition": "0x7fffffffffffff",
"eip98Transition": "0x7fffffffffffff",
"eip140Transition": "0x2a",
"eip155Transition": "0x2a",
"eip211Transition": "0x2a",
"eip214Transition": "0x2a",
"eip658Transition": "0x2a",
"maxCodeSize": "0x6000",
"maxCodeSizeTransition": "0x7fffffffffffff"
},
"genesis": {
"seal": {
"ethereum": {
"nonce": "0x000000000000002a",
"mixHash": "0x00000000000000000000000000000000000000647572616c65787365646c6578"
}
},
"difficulty": "0x3d0900",
"author": "0x0000000000000000000000000000000000000000",
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "",
"gasLimit": "0x7a1200"
},
"nodes": [
"enode://5ddc110733f6d34101973cdef3f9b43484159acf6f816d3b1ee92bc3c98ea453e857bb1207edf0ec0242008ab3a0f9f05eeaee99d47bd414c08a5bdf4847de13@176.9.3.148:30303",
"enode://38f074f4db8e64dfbaf87984bf290eef67772a901a7113d1b62f36216be152b8450c393d6fc562a5e38f04f99bc8f439a99010a230b1d92dc1df43bf0bd00615@176.9.3.148:30403"
],
"accounts": {
"0000000000000000000000000000000000000001": {
"balance": "1",
"builtin": {
"name": "ecrecover",
"pricing": {
"linear": {
"base": 3000,
"word": 0
}
}
}
},
"0000000000000000000000000000000000000002": {
"balance": "1",
"builtin": {
"name": "sha256",
"pricing": {
"linear": {
"base": 60,
"word": 12
}
}
}
},
"0000000000000000000000000000000000000003": {
"balance": "1",
"builtin": {
"name": "ripemd160",
"pricing": {
"linear": {
"base": 600,
"word": 120
}
}
}
},
"0000000000000000000000000000000000000004": {
"balance": "1",
"builtin": {
"name": "identity",
"pricing": {
"linear": {
"base": 15,
"word": 3
}
}
}
},
"0000000000000000000000000000000000000005": {
"builtin": {
"name": "modexp",
"activate_at": "0x2a",
"pricing": {
"modexp": {
"divisor": 20
}
}
}
},
"0000000000000000000000000000000000000006": {
"builtin": {
"name": "alt_bn128_add",
"activate_at": "0x2a",
"pricing": {
"linear": {
"base": 500,
"word": 0
}
}
}
},
"0000000000000000000000000000000000000007": {
"builtin": {
"name": "alt_bn128_mul",
"activate_at": "0x2a",
"pricing": {
"linear": {
"base": 40000,
"word": 0
}
}
}
},
"0000000000000000000000000000000000000008": {
"builtin": {
"name": "alt_bn128_pairing",
"activate_at": "0x2a",
"pricing": {
"alt_bn128_pairing": {
"base": 100000,
"pair": 80000
}
}
}
}
}
}

View File

@@ -10,12 +10,8 @@
"homesteadTransition":"0x118c30",
"eip100bTransition":"0x21e88e",
"blockReward":"0x1105a0185b50a80000",
"mcip3Transition":"0x124f81",
"mcip3MinerReward":"0xd8d726b7177a80000",
"mcip3UbiReward":"0x2b5e3af16b1880000",
"mcip3UbiContract":"0x00efdd5883ec628983e9063c7d969fe268bbf310",
"mcip3DevReward":"0xc249fdd327780000",
"mcip3DevContract":"0x00756cf8159095948496617f5fb17ed95059f536",
"blockRewardContractTransition": "0x124f81",
"blockRewardContractCode": "0x6080604052600436106100405763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663f91c28988114610045575b600080fd5b34801561005157600080fd5b50610071602460048035828101929082013591813591820191013561010a565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156100b557818101518382015260200161009d565b50505050905001838103825284818151815260200191508051906020019060200280838360005b838110156100f45781810151838201526020016100dc565b5050505090500194505050505060405180910390f35b6060808080600080803373fffffffffffffffffffffffffffffffffffffffe1461013357600080fd5b89881461013f57600080fd5b60408051600380825260808201909252906020820160608038833950506040805160038082526080820190925292975090506020820160608038833901905050935072efdd5883ec628983e9063c7d969fe268bbf3108560018151811015156101a457fe5b73ffffffffffffffffffffffffffffffffffffffff90921660209283029091019091015283516802b5e3af16b188000090859060019081106101e257fe5b60209081029091010152845172756cf8159095948496617f5fb17ed95059f536908690600290811061021057fe5b73ffffffffffffffffffffffffffffffffffffffff909216602092830290910190910152835167c249fdd327780000908590600290811061024d57fe5b60209081029091010152600092505b898310156103b75788888481811061027057fe5b9050602002013561ffff1661ffff166000141561030c578a8a8481811061029357fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff168560008151811015156102bf57fe5b73ffffffffffffffffffffffffffffffffffffffff9092166020928302909101909101528351680d8d726b7177a8000090859060009081106102fd57fe5b602090810290910101526103ac565b606489898581811061031a57fe5b9050602002013561ffff1661ffff161015156103ac57606489898581811061033e57fe5b9050602002013561ffff1603915060038260080361ffff16681105a0185b50a80000029060020a9004905061039d858c8c86818110151561037b57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff166103c8565b94506103a9848261049f565b93505b60019092019161025c565b509299919850909650505050505050565b606080600084516001016040519080825280602002602001820160405280156103fb578160200160208202803883390190505b509150600090505b845181101561045e57848181518110151561041a57fe5b90602001906020020151828281518110151561043257fe5b73ffffffffffffffffffffffffffffffffffffffff909216602092830290910190910152600101610403565b8382600184510381518110151561047157fe5b73ffffffffffffffffffffffffffffffffffffffff9290921660209283029190910190910152509392505050565b606080600084516001016040519080825280602002602001820160405280156104d2578160200160208202803883390190505b509150600090505b845181101561051b5784818151811015156104f157fe5b90602001906020020151828281518110151561050957fe5b602090810290910101526001016104da565b8382600184510381518110151561052e57fe5b60209081029190910101525093925050505600a165627a7a72305820c9ab92a56245040e76af5fc4f3ac4cf4315336b503db06677c21aa1e00aaa8e20029",
"difficultyBombDelays": {
"0x21e88e": 3000000
}

View File

@@ -1,56 +0,0 @@
{
"name": "Olympic",
"engine": {
"Ethash": {
"params": {
"minimumDifficulty": "0x020000",
"difficultyBoundDivisor": "0x0800",
"durationLimit": "0x08",
"blockReward": "0x14D1120D7B160000",
"homesteadTransition": "0x7fffffffffffffff"
}
}
},
"params": {
"gasLimitBoundDivisor": "0x0400",
"registrar": "5e70c0bbcd5636e0f9f9316e9f8633feb64d4050",
"accountStartNonce": "0x00",
"maximumExtraDataSize": "0x0400",
"minGasLimit": "125000",
"networkID" : "0x0",
"eip150Transition": "0x7fffffffffffffff",
"eip160Transition": "0x7fffffffffffffff",
"eip161abcTransition": "0x7fffffffffffffff",
"eip161dTransition": "0x7fffffffffffffff",
"eip98Transition": "0x7fffffffffffff",
"eip155Transition": "0x7fffffffffffffff"
},
"genesis": {
"seal": {
"ethereum": {
"nonce": "0x000000000000002a",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
},
"difficulty": "0x20000",
"author": "0x0000000000000000000000000000000000000000",
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x",
"gasLimit": "0x2fefd8"
},
"accounts": {
"0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
"0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
"0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
"0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
"dbdbdb2cbd23b783741e8d7fcf51e459b497e4a6": { "balance": "1606938044258990275541962092341162602522202993782792835301376" },
"e6716f9544a56c530d868e4bfbacb172315bdead": { "balance": "1606938044258990275541962092341162602522202993782792835301376" },
"b9c015918bdaba24b4ff057a92a3873d6eb201be": { "balance": "1606938044258990275541962092341162602522202993782792835301376" },
"1a26338f0d905e295fccb71fa9ea849ffa12aaf4": { "balance": "1606938044258990275541962092341162602522202993782792835301376" },
"2ef47100e0787b915105fd5e3f4ff6752079d5cb": { "balance": "1606938044258990275541962092341162602522202993782792835301376" },
"cd2a3d9f938e13cd947ec05abc7fe734df8dd826": { "balance": "1606938044258990275541962092341162602522202993782792835301376" },
"6c386a4b26f73c802f34673f7248bb118f97424a": { "balance": "1606938044258990275541962092341162602522202993782792835301376" },
"e4157b34ea9615cfbde6b4fda419828124b70c78": { "balance": "1606938044258990275541962092341162602522202993782792835301376" }
}
}

View File

@@ -62,8 +62,8 @@
"gasLimit": "0x1000000"
},
"hardcodedSync":{
"header": "f90217a00f0e017311206b97b47403eba05a16ada760a691a36f844ab8bc9082a4efedc9a067baeee20ae4f4216ab4b0c41198efd376aca23e44b1d6575c5949955547b72a946a9ecfa04e99726ec105517ac7ae1aba550bea6ca0e64d4fe9bee34d98e127f7f94f17535582d5bc6eeb6219f323b046b9a98c72b5a02d33ce5daab0436707c6d958dcf0bcd311ec7a72d7b33c20784178d5d95bc6e9a0a5b9cd4802fafaa9381ec0aa745cdb7ac953675e9df89474e5fe14fee134cf87b90100000008018000100000000000800000010000000050004000800000800014200010000001000000000001009001000000000000000000000000000000006004020600000000200001000108088002260441000020204000000000000000000280000000000200010001000000041008002000000004004c000000001000000000008000000000000800000400000201000000044001145000000000000001000a0200c04000a00010080100000020000000400002040000000000040000000040200001020000401000000800080080000400010000000200000008020020200000101000000000100400000000004400010020000200000000000001000000008453461c8683402001837a1200832c5216845bbd359199d88301080f846765746888676f312e31302e31856c696e7578a0c1da176f6642888b4369e14349ca7dc125ef7d4f5f7abad61bd7f6b95bfd46bf887d1a171a9f55dd67",
"totalDifficulty": "12027449412394243",
"header": "f90205a0cd611d63e443c91cba1dc259c71fdb96bb70a1b78639166f7aa2a09b36843f7da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940d85c541489b4c67df516b86898e1ed59c8d639aa039cdbfba9ee1e91d15fead004292a7df0865204ee878daab2375683cc527df2ca0ebf5b5fe0ef82be8bda42e6767ad7881269cefe650c3a899f38f5ed1c05cad8da0578f443c4b0d0bd89e42a855436258f1b19d1a018f6769c5be7aca0679ce6008b90100000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000008000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000800000000000000008501856ef4de83436801837a121d830e1038845bea0191864b564f544845a08dcfeee7d79d54276d8bc35765ade21a51d277540a3d7a8e17fc26b6324487e488d70f2a90307e2ae3",
"totalDifficulty": "14549054591321060",
"CHTs": [
"0x614648fc0a459451850bdfe353a932b5ff824e1b568478394f78b3ed5427e37a",
"0x1eae561c582dbb7f4e041998e084e165d0332c915d3a6da367638a8d24f3fafc",
@@ -2116,7 +2116,112 @@
"0x40384a52564fae5df8c3e41827cdf584e38f3f555a54ca749b7b516619071d85",
"0xe52f7c17a4106594563ae7b724e5613e87d8442177f39a36b946b0e335be0e5b",
"0x7726202a7c255a9d7be47af6f3b44c1e379cda61237866554396fb6ec043482c",
"0x665da353f296cde80e3cbcb9c7f93b107d5676e5cd694b0bd33334d74789beb9"
"0x665da353f296cde80e3cbcb9c7f93b107d5676e5cd694b0bd33334d74789beb9",
"0xa1157fb181aaa945793b029d3915b37103d050f1f695862d9cda90df4755c189",
"0x449c9daae1c38b3d3f6861b63dc611f147b8a29029927f85c32b5e549df8ee9d",
"0x5739fcf908f960416e5227ff6f95aeb00696f8eb7192968239458a0aebf42533",
"0xfaa6017362d6e64f9ae1b6d11764ddba77cd980261acb5bdbb17b7cdee2d3024",
"0x97fee586909cf8b3cfb2f2dd4e251cb642eb551f1e5d9fa557a21dcb66f430c0",
"0x9934d90e0b4ec5900107784116323b0f76d1d71491cf9c619520478b6eb97ded",
"0x8f5afe4fefb0de810442e27b2bce63e3a424f9e339a0e1f46f6ed26617a4a404",
"0xcd12ed1b75e624f93d9e4fe7dc65407b6d7963196e4082fb459ce354977355a1",
"0x6858ff0c07de87aa2a88498ae948efe6cffade00f3f21086f0a71b8364090846",
"0xaca944e99122e4fe41c62b88e67940332483c8aae2a3a615508f848ceb1c044e",
"0xa8bd3a6b9197bec8849737e6771f563d14d7415707776ce4bed9460588c55c9a",
"0x20e5f18e795844cfcf2326f52ab1e56f4a53a1ce405fd355e0d37de5f6d552ee",
"0x038821cd156d2d9e2aff1ce3525726c42f581ca3e9e2cc75df524a3dbdfe0feb",
"0xb79bd23e10d1e6c7ae749cecaa732966ce3c2e2ea8b640d43638f14d7b78a21c",
"0x2c4d3bcae4a76ffe6924555b320847211367ee37899b187d8fd4358d91264c2e",
"0x0896db7657d2aa8d02166bd4ceba7515b24147fcf0aa34223590fb80db64f848",
"0x95f3b077d9cff92709d46185a7dc5d723f257fb77641e436b0f1bf07947844a1",
"0x6fdd931a93229698b92e6419074bc308a372e0923b35321b725916c1c151cae0",
"0x8c337c36c2027d0f2fb96405f76d3190cdd01237f6a602e07976e09c4a2339e4",
"0x8091a859cf86c1e2c22c870ebc10334f50e05bac2a41153102bf3f698bf5156b",
"0x382435cc836bf1873e489cb4d42d1c1673c5d1b452ba2d16dbd1ca77b7b87a8c",
"0xac5a288b16ed708b00cbe956a14e2a64b321f40851ea25ab1aded7b096822ec6",
"0xee95229b736827a21e0b7154873da3da59e38a1ba3e3b1770de2ed973495ce23",
"0x5168b6e3b5274054fec17b94a82931bc229d0270e5e4c9aeb61539fe8ba4f4a3",
"0x588c6144dfbb33922873946a44f03092bd65d2f89a01b3973002ed38f48917bc",
"0x6c51a964953dc036043b6e8c7fba4a3f6e83295306767bcc3562d9a8cdb04497",
"0x2cfdde11cc2669c5b504c4a82c31ff03e3f0b3aff044519b44bc39405bbf3c9b",
"0xd93200e550400a7179ac7afc394b22b7c710192eadbf429389450e7167191fdb",
"0x5e32f497c606c01c9be8ce1cca5f3cf475f62cf38b2195244a7c93df7d064dde",
"0xb0b74e34fd3983aef31a0584b6a7483ee936622b5fffbdce1411a9db6171c685",
"0x69d0a96a2eca8d6a5c32e700d3f910330930a3348e98e5b276013fcf70c0fe5f",
"0xf49cbb26f2463d38fde553e483de2d4bc6dd85efe2d0e56a2a79810df6af6db9",
"0xe58aa167a26eadf11257f1fcb5da7eef50f9985b590320cc6c015176965ea58e",
"0x582f08d14023a661a9d9dfd1db8324be88fc631cb9136e92f379ad7703584414",
"0xb9c5e584f5e231c2c41b41799a945d60b7ec22487e587ef55e2d9710489c3c00",
"0xd8b70c6657a5bf1fa4b67c4fc046c1eda284d677c610dbacaf0d2d84e4d782dd",
"0x1e29fb536e468abf66b59dd6f48d177a5100a192f1807afc12bb5c97368b8c95",
"0x595ac042acdb51370bf6bfd2b2058dda4781dd7ec330474defb2d5dd00e7f50e",
"0x3d00887c6509b148c5fadde21014aae94924fef363fd5723d80d6a2028df1de5",
"0x9632d419c9fdc7e676b130806cb9c86631aade0adc6a129d3769908ff97e7ef3",
"0x2f91c7ce1158228c8264a6147c6ca396b0d536cdde997a922cde2772b786743f",
"0xf4c731ac2e2612b7e7afcf3ba5911a58a03ef075133923218f54a736b25acb81",
"0x6748a5143ad25f0a461257a47eeab8f057782a438274ced580ca2bd3725d6be3",
"0x05a113b04baf81b6396dd32d59a53908d07a374ebdf17314ec334b3330a16697",
"0xb1bafaef874da14b8a9f883f89a896ec37d9af1b0958f5a3867780278bfe940d",
"0xd93c67d29befe531330c37dfa8b64db7339c8ac35b8cb674d741a414d90d77ef",
"0xb4319281a05f00968367a349e626ec63227412193c30aaface14ac6f7a480024",
"0xf6dce891724a49024535047bee44f889d5228066a931a8f40c18c7efed60f31b",
"0xccdeb308e3402c7dc72588871c23fb4f6fdc60e2a63230f628c5a2951878535b",
"0x90958033b917eea42ffb8bf077ccab8b19c2448113e8a128815ab3441846404b",
"0xed3436553039948094f33cffaff91a7e2b1eab86b638de5c8eb09538c8df0a8e",
"0x0910ba3093e37abaf70ffc0ef6a3b9b82e8c5f7ae497eec14b753f23d0a25343",
"0xdc78d9fceec3add33b92e1a0ee402b80cd87946e0def46f284d26eac46be6bcd",
"0x1d71a82b8d4b89f73747d8073a36acf8496757d35bb452e9cfd74d758774f492",
"0x5399612937722b6fbcb90c1768a92bb35acd4da6168814c1d9deb6156cf35134",
"0xc7156ee3591ab91824b2d4868d28baf11855a63a801b3793f99fdde7867eac7f",
"0xd25b288f3333ea8e33b33f42edf7b64976281e4840599aa49b07da39f895073a",
"0xc6596a87c544e84cfaa2baaa4fb0a93f3fa9d1e6938426ea05a418568a1589b0",
"0xdbf30aa7f1cb3a6d7661934d7ea2ec0665843ea1ec9b05fddd77fdb33fa7d834",
"0xfac2628cb5d70c177e8defbf62b0448297ecb13962638b9a26c5d05203cb2937",
"0xe8c5a65edee74d59e7b9e2fb4779485958d95303fff95bfebc0c1f4bf24ef9bf",
"0x67d21b95f40ca7c991f37981393dcec3218e70d5402d82ecbfcb21ae532872bb",
"0xba19c10601ed47bffb755f791325c50af9229d5c25294f315116fdb3640ca35a",
"0xf4c026f65e31d4606541c4e679d30d7336cfeeb81e9893465eb08c310792c061",
"0x5425ff602e06947bda22cfb687ace85c10896b5d48de144149cba26bac9a35ae",
"0xe11f82e350c209213da7d977e2de5199559ad3793a24a226cb4be367c0aa3c4a",
"0x13fb0194f473a4af296184d3293005dffcd28f1cf4b986bdaacede4a0a096fa6",
"0x3dab80c9fc23caf409e38791f07e107da3b5d0d9d4a64f87164e6d455660591b",
"0x5901803b234ef0445acfcd884baf0777970d3b600b80ab137dc1015a5b790885",
"0x3735e2d0ac017cd2c0570830615ed9eb642183fee5b2c2155e5fefc1d4de2561",
"0xea9030afc249a1e4f6c86f4b19660ea63783824e8d1c3de30e38802f1aea9d12",
"0x9def3e76927de026a1a76f39c242263ffbf94b3ef42fb6e98626b67ec3d8a308",
"0x504886149f29d5eb02412202f04b45f23cc97a82206bdf237c433e83c52e386b",
"0xc84d3b9e84727c2d9279dfebcdf8104762e3b101dd9f39c9482a456f87bcf976",
"0xf4737cd864b198c8049ece5a4f18eea18b48a649997c42504b560188adfb6f2b",
"0x410894a208ff99bd3ec5f925aa7ff6932c4404390df9e337601fa7b7251d09ff",
"0xe6e7e7e2b54bcbe37eb7066b9a3c9b01b632d228c8ed5ef8f1871d9b7235a55b",
"0x8af02fe4657f956a9ede1a9b0a83d67367b43a8f5efdf6bd753d09f428b58960",
"0xdd056794fcb6f5b694934b17ef35577dbec8d04159fe447e0eba02e4ff4e9d96",
"0xef94a3289e9e197b04c17886373adbe66a451efe052fb419846006b5f659b91a",
"0x5558e5612dc3c222d76e7190409fc5d38479e08f6fdf4b7df299e6da968c2811",
"0x5f38cc5046a503d424c4b63cb060956babe0c1de050517d0067eccfa23cb664d",
"0x4c6a04827f46e51378e9ff3b811c878dead62da3ae20ef7d392c57512a09a719",
"0x68fd9806bea1d937063778b245a6788cd992e4fc614d5bce1ffe06e125f67701",
"0x0751a79f86c4220e81bbf6b4692976ed4c315f9b62937b23083f4db2370f04eb",
"0x5651840a2065a3468d97bf824e78455eb5e22b82b45fde7bb69b297c4c40e853",
"0x959d277feeb492ed3393fcd5774f1dde27c6018b07cc4fc93b937ee266ae12ea",
"0xa145f2ed353350a89de97e83433188adbd14107c16c654c131203442c34f2899",
"0xf888fc918eab6f88a5f6c6545d47a32dd558f10d00e86a9949cb3f144b7264e2",
"0x2fef7f5f1c149c87602cbe38766631abc992efaee26dd5b59e5bc361f6901cf4",
"0x5e0735a9be3eb97e790a93502a6f138a8863b0f0c20905bee0ac14d5aff4206a",
"0x9c40cbdab8e769c2c6f9de57c23621c5d8a25adaedd1ba9df17fa1680cd4e63f",
"0x995e6a00f5bc63f0a5d837a6671260771f12995b82da19c72a9546ae7b93f38f",
"0x10f647c754615b475543fca5ed9a4491503867fae619513dad966af63cb7ed2b",
"0x7e45b18bd06e946d20bc3807aa926aa5c0a10555b9dc18f9574136969b8f48d5",
"0x8a419fcb515eef5a139a37241872c095818fd276f77e6388c74b82ae49e6386f",
"0x2cb2d82e278d8ba47830ed3dbd6edf69d2e49721182488ffe0a01698071e7d40",
"0x1e9e5cb7a68e7a2decef900bd250bd31c1f024ddd240799327263c72940c7e59",
"0x3904821c4388b16e9851e3a7318f4177102da38525cd3e5e5708430a243470a1",
"0x7785b9d9ff6dfa45d945aaa393270bf8b62bbde46e941aa068606c173963e518",
"0xbff782fbbadfc752f5c2a239e49ab13200fc35cfba29a5332fe936a0367d336c",
"0x294a3fd73f102c7017c9208857dfb91ec7c323916dd1bb3c9f1fac2c7d952b4b",
"0x3a9fe3685814b6cff7a918e514a9d5375a1fc8268a48d5b78da93dfda115332f",
"0xc033a1836983d485e28e5a0825c953a76d4c7f4a8ec5f7eb0b11baf5ae2beb79",
"0xb088df91127cad5d72f8db96d7ea86dfdef55374bf982222a45df7d2b631ceb6"
]
},
"nodes": [

View File

@@ -1,468 +1,42 @@
{ "block":
[
{
"reference": "9590",
"failing": "stCreateTest",
"subtests": [
"CreateOOGafterInitCodeReturndata2_d0g1v0_Constantinople"
]
"reference": "None",
"comment": "This failing test is deemed skippable. Could not happen on a mainnet.",
"failing": "GeneralStateTest_stCreate2",
"subtests": ["RevertInCreateInInitCreate2_d0g0v0_Constantinople"]
},
{
"reference": "9590",
"failing": "stCreate2",
"subtests": [
"RevertDepthCreateAddressCollision_d0g1v0_Constantinople",
"RevertDepthCreateAddressCollision_d1g1v1_Constantinople",
"CREATE2_Suicide_d5g0v0_Constantinople",
"CREATE2_Suicide_d7g0v0_Constantinople",
"create2collisionSelfdestructedOOG_d2g0v0_Byzantium",
"create2collisionSelfdestructedOOG_d2g0v0_Constantinople",
"create2collisionNonce_d1g0v0_Byzantium",
"create2collisionNonce_d1g0v0_Constantinople",
"CreateMessageRevertedOOGInInit_d0g1v0_Constantinople",
"create2callPrecompiles_d3g0v0_Constantinople",
"create2collisionCode_d1g0v0_Byzantium",
"create2collisionCode_d1g0v0_Constantinople",
"create2collisionStorage_d0g0v0_Byzantium",
"create2collisionStorage_d0g0v0_Constantinople",
"create2callPrecompiles_d4g0v0_Constantinople",
"create2collisionSelfdestructedRevert_d0g0v0_Byzantium",
"create2collisionSelfdestructedRevert_d0g0v0_Constantinople",
"CreateMessageReverted_d0g1v0_Constantinople",
"RevertOpcodeCreate_d0g1v0_Constantinople",
"CREATE2_Suicide_d11g0v0_Constantinople",
"create2checkFieldsInInitcode_d5g0v0_Constantinople",
"create2collisionSelfdestructedOOG_d1g0v0_Byzantium",
"create2collisionSelfdestructedOOG_d1g0v0_Constantinople",
"returndatacopy_following_create_d1g0v0_Constantinople",
"RevertDepthCreate2OOG_d1g1v1_Constantinople",
"create2collisionSelfdestructed_d2g0v0_Byzantium",
"create2collisionSelfdestructed_d2g0v0_Constantinople",
"create2callPrecompiles_d2g0v0_Constantinople",
"create2InitCodes_d2g0v0_Constantinople",
"create2collisionNonce_d2g0v0_Byzantium",
"create2collisionNonce_d2g0v0_Constantinople",
"create2collisionCode_d0g0v0_Byzantium",
"create2collisionCode_d0g0v0_Constantinople",
"CREATE2_Bounds_d0g0v0_Constantinople",
"RevertDepthCreate2OOG_d0g0v0_Constantinople",
"CREATE2_Suicide_d1g0v0_Constantinople",
"CREATE2_Bounds3_d0g1v0_Constantinople",
"create2collisionStorage_d2g0v0_Byzantium",
"create2collisionStorage_d2g0v0_Constantinople",
"RevertDepthCreateAddressCollision_d0g0v1_Constantinople",
"create2callPrecompiles_d5g0v0_Constantinople",
"create2collisionCode2_d0g0v0_Byzantium",
"create2collisionCode2_d0g0v0_Constantinople",
"create2noCash_d0g0v0_Byzantium",
"create2noCash_d0g0v0_Constantinople",
"create2checkFieldsInInitcode_d7g0v0_Constantinople",
"create2SmartInitCode_d1g0v0_Constantinople",
"create2InitCodes_d6g0v0_Constantinople",
"create2noCash_d1g0v0_Byzantium",
"create2noCash_d1g0v0_Constantinople",
"CREATE2_ContractSuicideDuringInit_ThenStoreThenReturn_d0g0v0_Constantinople",
"RevertOpcodeInCreateReturns_d0g0v0_Constantinople",
"create2collisionStorage_d1g0v0_Byzantium",
"create2collisionStorage_d1g0v0_Constantinople",
"create2checkFieldsInInitcode_d3g0v0_Constantinople",
"create2collisionBalance_d0g0v0_Byzantium",
"create2collisionBalance_d0g0v0_Constantinople",
"create2collisionSelfdestructed2_d0g0v0_Constantinople",
"create2InitCodes_d3g0v0_Constantinople",
"create2collisionCode2_d1g0v0_Byzantium",
"create2collisionCode2_d1g0v0_Constantinople",
"create2checkFieldsInInitcode_d1g0v0_Constantinople",
"create2collisionBalance_d1g0v0_Byzantium",
"create2collisionBalance_d1g0v0_Constantinople",
"CREATE2_Bounds3_d0g2v0_Constantinople",
"create2callPrecompiles_d6g0v0_Constantinople",
"Create2Recursive_d0g0v0_Constantinople",
"create2collisionSelfdestructedOOG_d0g0v0_Byzantium",
"create2collisionSelfdestructedOOG_d0g0v0_Constantinople",
"CREATE2_Suicide_d3g0v0_Constantinople",
"returndatacopy_following_create_d0g0v0_Constantinople",
"create2InitCodes_d8g0v0_Constantinople",
"RevertDepthCreate2OOG_d0g0v1_Constantinople",
"create2checkFieldsInInitcode_d2g0v0_Constantinople",
"RevertDepthCreate2OOG_d1g0v1_Constantinople",
"Create2OnDepth1024_d0g0v0_Constantinople",
"create2collisionSelfdestructed2_d1g0v0_Constantinople",
"create2collisionSelfdestructedRevert_d2g0v0_Byzantium",
"create2collisionSelfdestructedRevert_d2g0v0_Constantinople",
"create2callPrecompiles_d0g0v0_Constantinople",
"RevertDepthCreateAddressCollision_d0g1v1_Constantinople",
"create2collisionSelfdestructed_d1g0v0_Byzantium",
"create2collisionSelfdestructed_d1g0v0_Constantinople",
"call_outsize_then_create2_successful_then_returndatasize_d0g0v0_Byzantium",
"call_outsize_then_create2_successful_then_returndatasize_d0g0v0_Constantinople",
"Create2OOGafterInitCodeRevert_d0g0v0_Constantinople",
"Create2OOGafterInitCodeReturndata3_d0g0v0_Constantinople",
"Create2OOGafterInitCodeReturndataSize_d0g0v0_Constantinople",
"create2InitCodes_d7g0v0_Constantinople",
"CREATE2_Suicide_d10g0v0_Constantinople",
"RevertDepthCreate2OOG_d0g1v0_Constantinople",
"create2InitCodes_d5g0v0_Constantinople",
"create2collisionSelfdestructedRevert_d1g0v0_Byzantium",
"create2collisionSelfdestructedRevert_d1g0v0_Constantinople",
"RevertDepthCreate2OOG_d1g1v0_Constantinople",
"create2collisionSelfdestructed_d0g0v0_Byzantium",
"create2collisionSelfdestructed_d0g0v0_Constantinople",
"create2noCash_d2g0v0_Byzantium",
"create2noCash_d2g0v0_Constantinople",
"CREATE2_Bounds3_d0g0v0_Constantinople",
"create2collisionNonce_d0g0v0_Byzantium",
"create2collisionNonce_d0g0v0_Constantinople",
"CREATE2_Suicide_d2g0v0_Constantinople",
"Create2OOGafterInitCode_d0g0v0_Constantinople",
"call_then_create2_successful_then_returndatasize_d0g0v0_Byzantium",
"call_then_create2_successful_then_returndatasize_d0g0v0_Constantinople",
"create2collisionBalance_d2g0v0_Byzantium",
"create2collisionBalance_d2g0v0_Constantinople",
"create2checkFieldsInInitcode_d6g0v0_Constantinople",
"RevertDepthCreate2OOG_d0g1v1_Constantinople",
"returndatacopy_afterFailing_create_d0g0v0_Constantinople",
"returndatacopy_following_revert_in_create_d0g0v0_Constantinople",
"CREATE2_Suicide_d9g0v0_Constantinople",
"create2callPrecompiles_d7g0v0_Constantinople",
"RevertDepthCreateAddressCollision_d1g0v1_Constantinople",
"create2InitCodes_d1g0v0_Constantinople",
"CREATE2_Bounds_d0g1v0_Constantinople",
"Create2OOGafterInitCodeReturndata_d0g0v0_Constantinople",
"create2checkFieldsInInitcode_d4g0v0_Constantinople",
"CreateMessageRevertedOOGInInit_d0g0v0_Constantinople",
"RevertDepthCreateAddressCollision_d1g1v0_Constantinople",
"returndatacopy_following_successful_create_d0g0v0_Constantinople",
"create2checkFieldsInInitcode_d0g0v0_Constantinople",
"CreateMessageReverted_d0g0v0_Constantinople",
"create2SmartInitCode_d0g0v0_Constantinople",
"CREATE2_Bounds2_d0g0v0_Constantinople",
"returndatasize_following_successful_create_d0g0v0_Constantinople",
"CREATE2_Bounds2_d0g1v0_Constantinople",
"returndatacopy_0_0_following_successful_create_d0g0v0_Constantinople",
"RevertDepthCreateAddressCollision_d0g0v0_Constantinople",
"CREATE2_Suicide_d0g0v0_Constantinople",
"create2InitCodes_d0g0v0_Constantinople",
"Create2OnDepth1023_d0g0v0_Constantinople",
"create2InitCodes_d4g0v0_Constantinople",
"Create2OOGafterInitCodeReturndata2_d0g0v0_Constantinople",
"create2collisionBalance_d3g0v0_Byzantium",
"create2collisionBalance_d3g0v0_Constantinople",
"CREATE2_Suicide_d4g0v0_Constantinople",
"Create2OOGafterInitCode_d0g1v0_Constantinople",
"RevertDepthCreateAddressCollision_d1g0v0_Constantinople",
"Create2OOGafterInitCodeRevert2_d0g0v0_Constantinople",
"Create2OOGafterInitCodeReturndata_d0g1v0_Constantinople",
"Create2Recursive_d0g1v0_Constantinople",
"create2collisionCode_d2g0v0_Byzantium",
"create2collisionCode_d2g0v0_Constantinople",
"CREATE2_Suicide_d6g0v0_Constantinople",
"CREATE2_Suicide_d8g0v0_Constantinople",
"RevertOpcodeCreate_d0g0v0_Constantinople",
"Create2OOGafterInitCodeReturndata2_d0g1v0_Constantinople",
"create2callPrecompiles_d1g0v0_Constantinople",
"RevertInCreateInInit_d0g0v0_Constantinople",
"RevertDepthCreate2OOG_d1g0v0_Constantinople"
]
},
{
"reference": "9590",
"failing": "bcStateTest",
"subtests": [
"suicideStorageCheck_Byzantium",
"suicideStorageCheck_Constantinople",
"suicideStorageCheckVCreate2_Byzantium",
"suicideStorageCheckVCreate2_Constantinople",
"create2collisionwithSelfdestructSameBlock_Constantinople",
"blockhashNonConstArg_Constantinople",
"suicideThenCheckBalance_Constantinople",
"suicideThenCheckBalance_Homestead",
"suicideStorageCheckVCreate_Byzantium",
"suicideStorageCheckVCreate_Constantinople"
]
},
{
"reference": "9590",
"failing": "stEIP158Specific",
"subtests": [
"callToEmptyThenCallError_d0g0v0_Byzantium",
"callToEmptyThenCallError_d0g0v0_Constantinople",
"callToEmptyThenCallError_d0g0v0_EIP158"
]
},
{
"reference": "9590",
"failing": "stPreCompiledContracts",
"subtests": [
"identity_to_smaller_d0g0v0_Constantinople",
"identity_to_bigger_d0g0v0_Constantinople"
]
},
{
"reference": "9590",
"failing": "stReturnDataTest",
"subtests": [
"modexp_modsize0_returndatasize_d0g1v0_Constantinople",
"modexp_modsize0_returndatasize_d0g2v0_Constantinople",
"modexp_modsize0_returndatasize_d0g3v0_Constantinople"
]
},
{
"reference": "9590",
"failing": "stSpecialTest",
"subtests": [
"push32withoutByte_d0g0v0_Constantinople"
]
"reference": "None",
"comment": "This failing test is deemed skippable. Could not happen on a mainnet.",
"failing": "GeneralStateTest_stRevertTest",
"subtests": ["RevertInCreateInInit_d0g0v0_Constantinople"]
}
],
"state":
[
{
"reference": "9590",
"failing": "stCreateTest",
"reference": "None",
"comment": "This failing test is deemed skippable. Could not happen on a mainnet.",
"failing": "stCreate2Test",
"subtests": {
"CreateOOGafterInitCodeReturndata2": {
"subnumbers": ["2"],
"RevertInCreateInInitCreate2": {
"subnumbers": ["1"],
"chain": "Constantinople (test)"
}
}
},
{
"reference": "9590",
"failing": "stCreate2Test",
"reference": "None",
"comment": "This failing test is deemed skippable. Could not happen on a mainnet.",
"failing": "stRevertTest",
"subtests": {
"RevertInCreateInInit": {
"subnumbers": ["1"],
"chain": "Constantinople (test)"
}
}
},
{
"reference": "9590",
"failing": "stEIP150Specific",
"subtests": {
"NewGasPriceForCodes": {
"subnumbers": ["1"],
"chain": "Constantinople (test)"
}
}
},
{
"reference": "9590",
"failing": "stInitCodeTest",
"subtests": {
"OutOfGasContractCreation": {
"subnumbers": ["4"],
"chain": "Constantinople (test)"
}
}
},
{
"reference": "9590",
"failing": "stPreCompiledContracts",
"subtests": {
"modexp": {
"subnumbers": ["*"],
"chain": "Constantinople (test)"
}
}
},
{
"reference": "9590",
"failing": "stRevertTest",
"subtests": {
"LoopCallsDepthThenRevert3": {
"subnumbers": ["1"],
"chain": "Constantinople (test)"
},
"RevertOpcodeCreate": {
"subnumbers": ["1"],
"chain": "Constantinople (test)"
},
"RevertSubCallStorageOOG2": {
"subnumbers": ["1","3"],
"chain": "Constantinople (test)"
},
"RevertDepthCreateOOG": {
"subnumbers": ["3","4"],
"chain": "Constantinople (test)"
},
"RevertOpcodeMultipleSubCalls": {
"subnumbers": ["*"],
"chain": "Constantinople (test)"
},
"RevertOpcodeDirectCall": {
"subnumbers": ["1","2"],
"chain": "Constantinople (test)"
},
"LoopCallsDepthThenRevert2": {
"subnumbers": ["1"],
"chain": "Constantinople (test)"
},
"RevertDepth2": {
"subnumbers": ["1"],
"chain": "Constantinople (test)"
},
"RevertRemoteSubCallStorageOOG2": {
"subnumbers": ["1","2"],
"chain": "Constantinople (test)"
},
"RevertDepthCreateAddressCollision": {
"subnumbers": ["3","4"],
"chain": "Constantinople (test)"
}
}
},
{
"reference": "9590",
"failing": "stStaticCall",
"subtests": {
"static_RevertDepth2": {
"subnumbers": ["1","3"],
"chain": "Constantinople (test)"
},
"static_CheckOpcodes4": {
"subnumbers": ["3"],
"chain": "Constantinople (test)"
},
"static_CheckOpcodes3": {
"subnumbers": ["5","6","7","8"],
"chain": "Constantinople (test)"
},
"static_callBasic": {
"subnumbers": ["1","2"],
"chain": "Constantinople (test)"
},
"static_CheckOpcodes2": {
"subnumbers": ["5","6","7","8"],
"chain": "Constantinople (test)"
},
"static_callCreate": {
"subnumbers": ["2"],
"chain": "Constantinople (test)"
}
}
},
{
"reference": "https://github.com/ethereum/tests/issues/512",
"failing": "stZeroKnowledge",
"subtests": {
"pointAddTrunc": {
"subnumbers": ["*"],
"chain": "Constantinople (test)"
},
"pointAdd": {
"subnumbers": ["*"],
"chain": "Constantinople (test)"
},
"pointMulAdd": {
"subnumbers": ["*"],
"chain": "Constantinople (test)"
},
"pointMulAdd2": {
"subnumbers": ["*"],
"chain": "Constantinople (test)"
}
}
},
{
"reference": "9590",
"failing": "stCreate2Test",
"subtests": {
"call_then_create2_successful_then_returndatasize": {
"subnumbers": ["1"],
"chain": "Constantinople (test)"
},
"returndatacopy_afterFailing_create": {
"subnumbers": ["1"],
"chain": "Constantinople (test)"
},
"create2checkFieldsInInitcode": {
"subnumbers": ["1","2","3","5","6","7"],
"chain": "Constantinople (test)"
},
"Create2Recursive": {
"subnumbers": ["*"],
"chain": "Constantinople (test)"
},
"create2collisionBalance": {
"subnumbers": ["2","3"],
"chain": "Constantinople (test)"
},
"create2InitCodes": {
"subnumbers": ["1","5","6","7","8","9"],
"chain": "Constantinople (test)"
},
"Create2OOGafterInitCode": {
"subnumbers": ["2"],
"chain": "Constantinople (test)"
},
"CreateMessageRevertedOOGInInit": {
"subnumbers": ["2"],
"chain": "Constantinople (test)"
},
"returndatacopy_following_revert_in_create": {
"subnumbers": ["*"],
"chain": "Constantinople (test)"
},
"create2collisionSelfdestructed": {
"subnumbers": ["2"],
"chain": "Constantinople (test)"
},
"returndatacopy_0_0_following_successful_create": {
"subnumbers": ["*"],
"chain": "Constantinople (test)"
},
"Create2OnDepth1023": {
"subnumbers": ["*"],
"chain": "Constantinople (test)"
},
"Create2OOGafterInitCodeReturndata2": {
"subnumbers": ["2"],
"chain": "Constantinople (test)"
},
"RevertOpcodeInCreateReturns": {
"subnumbers": ["*"],
"chain": "Constantinople (test)"
},
"CREATE2_ContractSuicideDuringInit_ThenStoreThenReturn": {
"subnumbers": ["*"],
"chain": "Constantinople (test)"
},
"returndatasize_following_successful_create": {
"subnumbers": ["*"],
"chain": "Constantinople (test)"
},
"call_outsize_then_create2_successful_then_returndatasize": {
"subnumbers": ["*"],
"chain": "Constantinople (test)"
},
"CreateMessageReverted": {
"subnumbers": ["2"],
"chain": "Constantinople (test)"
},
"CREATE2_Suicide": {
"subnumbers": ["*"],
"chain": "Constantinople (test)"
},
"Create2OOGafterInitCodeRevert": {
"subnumbers": ["*"],
"chain": "Constantinople (test)"
},
"Create2OnDepth1024": {
"subnumbers": ["*"],
"chain": "Constantinople (test)"
},
"create2collisionStorage": {
"subnumbers": ["2","3"],
"chain": "Constantinople (test)"
},
"create2callPrecompiles": {
"subnumbers": ["*"],
"chain": "Constantinople (test)"
}
}
}
]
}

View File

@@ -106,7 +106,13 @@ impl ClientService {
info!("Configured for {} using {} engine", Colour::White.bold().paint(spec.name.clone()), Colour::Yellow.bold().paint(spec.engine.name()));
let pruning = config.pruning;
let client = Client::new(config, &spec, blockchain_db.clone(), miner.clone(), io_service.channel())?;
let client = Client::new(
config,
&spec,
blockchain_db.clone(),
miner.clone(),
io_service.channel(),
)?;
miner.set_io_channel(io_service.channel());
miner.set_in_chain_checker(&client.clone());
@@ -117,7 +123,7 @@ impl ClientService {
pruning: pruning,
channel: io_service.channel(),
snapshot_root: snapshot_path.into(),
db_restore: client.clone(),
client: client.clone(),
};
let snapshot = Arc::new(SnapshotService::new(snapshot_params)?);

View File

@@ -58,7 +58,7 @@ impl Default for Factory {
impl Factory {
/// Create a read-only accountdb.
/// This will panic when write operations are called.
pub fn readonly<'db>(&self, db: &'db HashDB<KeccakHasher>, address_hash: H256) -> Box<HashDB<KeccakHasher> + 'db> {
pub fn readonly<'db>(&self, db: &'db HashDB<KeccakHasher, DBValue>, address_hash: H256) -> Box<HashDB<KeccakHasher, DBValue> + 'db> {
match *self {
Factory::Mangled => Box::new(AccountDB::from_hash(db, address_hash)),
Factory::Plain => Box::new(Wrapping(db)),
@@ -66,7 +66,7 @@ impl Factory {
}
/// Create a new mutable hashdb.
pub fn create<'db>(&self, db: &'db mut HashDB<KeccakHasher>, address_hash: H256) -> Box<HashDB<KeccakHasher> + 'db> {
pub fn create<'db>(&self, db: &'db mut HashDB<KeccakHasher, DBValue>, address_hash: H256) -> Box<HashDB<KeccakHasher, DBValue> + 'db> {
match *self {
Factory::Mangled => Box::new(AccountDBMut::from_hash(db, address_hash)),
Factory::Plain => Box::new(WrappingMut(db)),
@@ -78,19 +78,19 @@ impl Factory {
/// DB backend wrapper for Account trie
/// Transforms trie node keys for the database
pub struct AccountDB<'db> {
db: &'db HashDB<KeccakHasher>,
db: &'db HashDB<KeccakHasher, DBValue>,
address_hash: H256,
}
impl<'db> AccountDB<'db> {
/// Create a new AccountDB from an address.
#[cfg(test)]
pub fn new(db: &'db HashDB<KeccakHasher>, address: &Address) -> Self {
pub fn new(db: &'db HashDB<KeccakHasher, DBValue>, address: &Address) -> Self {
Self::from_hash(db, keccak(address))
}
/// Create a new AcountDB from an address' hash.
pub fn from_hash(db: &'db HashDB<KeccakHasher>, address_hash: H256) -> Self {
pub fn from_hash(db: &'db HashDB<KeccakHasher, DBValue>, address_hash: H256) -> Self {
AccountDB {
db: db,
address_hash: address_hash,
@@ -98,12 +98,12 @@ impl<'db> AccountDB<'db> {
}
}
impl<'db> AsHashDB<KeccakHasher> for AccountDB<'db> {
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> { self }
impl<'db> AsHashDB<KeccakHasher, DBValue> for AccountDB<'db> {
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> { self }
}
impl<'db> HashDB<KeccakHasher> for AccountDB<'db> {
impl<'db> HashDB<KeccakHasher, DBValue> for AccountDB<'db> {
fn keys(&self) -> HashMap<H256, i32> {
unimplemented!()
}
@@ -137,19 +137,19 @@ impl<'db> HashDB<KeccakHasher> for AccountDB<'db> {
/// DB backend wrapper for Account trie
pub struct AccountDBMut<'db> {
db: &'db mut HashDB<KeccakHasher>,
db: &'db mut HashDB<KeccakHasher, DBValue>,
address_hash: H256,
}
impl<'db> AccountDBMut<'db> {
/// Create a new AccountDB from an address.
#[cfg(test)]
pub fn new(db: &'db mut HashDB<KeccakHasher>, address: &Address) -> Self {
pub fn new(db: &'db mut HashDB<KeccakHasher, DBValue>, address: &Address) -> Self {
Self::from_hash(db, keccak(address))
}
/// Create a new AcountDB from an address' hash.
pub fn from_hash(db: &'db mut HashDB<KeccakHasher>, address_hash: H256) -> Self {
pub fn from_hash(db: &'db mut HashDB<KeccakHasher, DBValue>, address_hash: H256) -> Self {
AccountDBMut {
db: db,
address_hash: address_hash,
@@ -162,7 +162,7 @@ impl<'db> AccountDBMut<'db> {
}
}
impl<'db> HashDB<KeccakHasher> for AccountDBMut<'db>{
impl<'db> HashDB<KeccakHasher, DBValue> for AccountDBMut<'db>{
fn keys(&self) -> HashMap<H256, i32> {
unimplemented!()
}
@@ -208,19 +208,19 @@ impl<'db> HashDB<KeccakHasher> for AccountDBMut<'db>{
}
}
impl<'db> AsHashDB<KeccakHasher> for AccountDBMut<'db> {
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> { self }
impl<'db> AsHashDB<KeccakHasher, DBValue> for AccountDBMut<'db> {
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> { self }
}
struct Wrapping<'db>(&'db HashDB<KeccakHasher>);
struct Wrapping<'db>(&'db HashDB<KeccakHasher, DBValue>);
impl<'db> AsHashDB<KeccakHasher> for Wrapping<'db> {
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> { self }
impl<'db> AsHashDB<KeccakHasher, DBValue> for Wrapping<'db> {
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> { self }
}
impl<'db> HashDB<KeccakHasher> for Wrapping<'db> {
impl<'db> HashDB<KeccakHasher, DBValue> for Wrapping<'db> {
fn keys(&self) -> HashMap<H256, i32> {
unimplemented!()
}
@@ -252,13 +252,13 @@ impl<'db> HashDB<KeccakHasher> for Wrapping<'db> {
}
}
struct WrappingMut<'db>(&'db mut HashDB<KeccakHasher>);
impl<'db> AsHashDB<KeccakHasher> for WrappingMut<'db> {
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> { self }
struct WrappingMut<'db>(&'db mut HashDB<KeccakHasher, DBValue>);
impl<'db> AsHashDB<KeccakHasher, DBValue> for WrappingMut<'db> {
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> { self }
}
impl<'db> HashDB<KeccakHasher> for WrappingMut<'db>{
impl<'db> HashDB<KeccakHasher, DBValue> for WrappingMut<'db>{
fn keys(&self) -> HashMap<H256, i32> {
unimplemented!()
}

View File

@@ -160,11 +160,6 @@ pub trait BlockProvider {
.and_then(|n| body.view().localized_transaction_at(&address.block_hash, n, address.index)))
}
/// Get transaction receipt.
fn transaction_receipt(&self, address: &TransactionAddress) -> Option<Receipt> {
self.block_receipts(&address.block_hash).and_then(|br| br.receipts.into_iter().nth(address.index))
}
/// Get a list of transactions for a given block.
/// Returns None if block does not exist.
fn transactions(&self, hash: &H256) -> Option<Vec<LocalizedTransaction>> {
@@ -234,6 +229,7 @@ pub struct BlockChain {
cache_man: Mutex<CacheManager<CacheId>>,
pending_best_ancient_block: RwLock<Option<Option<BestAncientBlock>>>,
pending_best_block: RwLock<Option<BestBlock>>,
pending_block_hashes: RwLock<HashMap<BlockNumber, H256>>,
pending_block_details: RwLock<HashMap<H256, BlockDetails>>,
@@ -543,6 +539,7 @@ impl BlockChain {
block_receipts: RwLock::new(HashMap::new()),
db: db.clone(),
cache_man: Mutex::new(cache_man),
pending_best_ancient_block: RwLock::new(None),
pending_best_block: RwLock::new(None),
pending_block_hashes: RwLock::new(HashMap::new()),
pending_block_details: RwLock::new(HashMap::new()),
@@ -813,18 +810,7 @@ impl BlockChain {
}, is_best);
if is_ancient {
let mut best_ancient_block = self.best_ancient_block.write();
let ancient_number = best_ancient_block.as_ref().map_or(0, |b| b.number);
if self.block_hash(block_number + 1).is_some() {
batch.delete(db::COL_EXTRA, b"ancient");
*best_ancient_block = None;
} else if block_number > ancient_number {
batch.put(db::COL_EXTRA, b"ancient", &hash);
*best_ancient_block = Some(BestAncientBlock {
hash: hash,
number: block_number,
});
}
self.set_best_ancient_block(block_number, &hash, batch);
}
false
@@ -865,6 +851,84 @@ impl BlockChain {
}
}
/// Update the best ancient block to the given hash, after checking that
/// it's directly linked to the currently known best ancient block
pub fn update_best_ancient_block(&self, hash: &H256) {
// Get the block view of the next ancient block (it must
// be in DB at this point)
let block_view = match self.block(hash) {
Some(v) => v,
None => return,
};
// So that `best_ancient_block` gets unlocked before calling
// `set_best_ancient_block`
{
// Get the target hash ; if there are no ancient block,
// it means that the chain is already fully linked
// Release the `best_ancient_block` RwLock
let target_hash = {
let best_ancient_block = self.best_ancient_block.read();
let cur_ancient_block = match *best_ancient_block {
Some(ref b) => b,
None => return,
};
// Ensure that the new best ancient block is after the current one
if block_view.number() <= cur_ancient_block.number {
return;
}
cur_ancient_block.hash.clone()
};
let mut block_hash = *hash;
let mut is_linked = false;
loop {
if block_hash == target_hash {
is_linked = true;
break;
}
match self.block_details(&block_hash) {
Some(block_details) => {
block_hash = block_details.parent;
},
None => break,
}
}
if !is_linked {
trace!(target: "blockchain", "The given block {:x} is not linked to the known ancient block {:x}", hash, target_hash);
return;
}
}
let mut batch = self.db.key_value().transaction();
self.set_best_ancient_block(block_view.number(), hash, &mut batch);
self.db.key_value().write(batch).expect("Low level database error.");
}
/// Set the best ancient block with the given value: private method
/// `best_ancient_block` must not be locked, otherwise a DeadLock would occur
fn set_best_ancient_block(&self, block_number: BlockNumber, block_hash: &H256, batch: &mut DBTransaction) {
let mut pending_best_ancient_block = self.pending_best_ancient_block.write();
let ancient_number = self.best_ancient_block.read().as_ref().map_or(0, |b| b.number);
if self.block_hash(block_number + 1).is_some() {
trace!(target: "blockchain", "The two ends of the chain have met.");
batch.delete(db::COL_EXTRA, b"ancient");
*pending_best_ancient_block = Some(None);
} else if block_number > ancient_number {
trace!(target: "blockchain", "Updating the best ancient block to {}.", block_number);
batch.put(db::COL_EXTRA, b"ancient", &block_hash);
*pending_best_ancient_block = Some(Some(BestAncientBlock {
hash: *block_hash,
number: block_number,
}));
}
}
/// Insert an epoch transition. Provide an epoch number being transitioned to
/// and epoch transition object.
///
@@ -1117,15 +1181,21 @@ impl BlockChain {
/// Apply pending insertion updates
pub fn commit(&self) {
let mut pending_best_ancient_block = self.pending_best_ancient_block.write();
let mut pending_best_block = self.pending_best_block.write();
let mut pending_write_hashes = self.pending_block_hashes.write();
let mut pending_block_details = self.pending_block_details.write();
let mut pending_write_txs = self.pending_transaction_addresses.write();
let mut best_block = self.best_block.write();
let mut best_ancient_block = self.best_ancient_block.write();
let mut write_block_details = self.block_details.write();
let mut write_hashes = self.block_hashes.write();
let mut write_txs = self.transaction_addresses.write();
// update best ancient block
if let Some(block_option) = pending_best_ancient_block.take() {
*best_ancient_block = block_option;
}
// update best block
if let Some(block) = pending_best_block.take() {
*best_block = block;

View File

@@ -51,7 +51,7 @@ impl Block {
#[inline]
pub fn encoded(&self) -> encoded::Block {
encoded::Block::new(encode(self).into_vec())
encoded::Block::new(encode(self))
}
#[inline]

View File

@@ -311,35 +311,51 @@ impl Impl for Ripemd160 {
}
}
// calculate modexp: exponentiation by squaring. the `num` crate has pow, but not modular.
fn modexp(mut base: BigUint, mut exp: BigUint, modulus: BigUint) -> BigUint {
use num::Integer;
// calculate modexp: left-to-right binary exponentiation to keep multiplicands lower
fn modexp(mut base: BigUint, exp: Vec<u8>, modulus: BigUint) -> BigUint {
const BITS_PER_DIGIT: usize = 8;
if modulus <= BigUint::one() { // n^m % 0 || n^m % 1
// n^m % 0 || n^m % 1
if modulus <= BigUint::one() {
return BigUint::zero();
}
if exp.is_zero() { // n^0 % m
// normalize exponent
let mut exp = exp.into_iter().skip_while(|d| *d == 0).peekable();
// n^0 % m
if let None = exp.peek() {
return BigUint::one();
}
if base.is_zero() { // 0^n % m, n>0
// 0^n % m, n > 0
if base.is_zero() {
return BigUint::zero();
}
let mut result = BigUint::one();
base = base % &modulus;
// fast path for base divisible by modulus.
// Fast path for base divisible by modulus.
if base.is_zero() { return BigUint::zero() }
while !exp.is_zero() {
if exp.is_odd() {
result = (result * &base) % &modulus;
}
exp = exp >> 1;
base = (base.clone() * base) % &modulus;
// Left-to-right binary exponentiation (Handbook of Applied Cryptography - Algorithm 14.79).
// http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
let mut result = BigUint::one();
for digit in exp {
let mut mask = 1 << (BITS_PER_DIGIT - 1);
for _ in 0..BITS_PER_DIGIT {
result = &result * &result % &modulus;
if digit & mask > 0 {
result = result * &base % &modulus;
}
mask >>= 1;
}
}
result
}
@@ -366,15 +382,19 @@ impl Impl for ModexpImpl {
} else {
// read the numbers themselves.
let mut buf = vec![0; max(mod_len, max(base_len, exp_len))];
let mut read_num = |len| {
let mut read_num = |reader: &mut io::Chain<&[u8], io::Repeat>, len: usize| {
reader.read_exact(&mut buf[..len]).expect("reading from zero-extended memory cannot fail; qed");
BigUint::from_bytes_be(&buf[..len])
};
let base = read_num(base_len);
let exp = read_num(exp_len);
let modulus = read_num(mod_len);
modexp(base, exp, modulus)
let base = read_num(&mut reader, base_len);
let mut exp_buf = vec![0; exp_len];
reader.read_exact(&mut exp_buf[..exp_len]).expect("reading from zero-extended memory cannot fail; qed");
let modulus = read_num(&mut reader, mod_len);
modexp(base, exp_buf, modulus)
};
// write output to given memory, left padded and same length as the modulus.
@@ -551,31 +571,31 @@ mod tests {
let mut base = BigUint::parse_bytes(b"12345", 10).unwrap();
let mut exp = BigUint::zero();
let mut modulus = BigUint::parse_bytes(b"789", 10).unwrap();
assert_eq!(me(base, exp, modulus), BigUint::one());
assert_eq!(me(base, exp.to_bytes_be(), modulus), BigUint::one());
// 0^n % m == 0
base = BigUint::zero();
exp = BigUint::parse_bytes(b"12345", 10).unwrap();
modulus = BigUint::parse_bytes(b"789", 10).unwrap();
assert_eq!(me(base, exp, modulus), BigUint::zero());
assert_eq!(me(base, exp.to_bytes_be(), modulus), BigUint::zero());
// n^m % 1 == 0
base = BigUint::parse_bytes(b"12345", 10).unwrap();
exp = BigUint::parse_bytes(b"789", 10).unwrap();
modulus = BigUint::one();
assert_eq!(me(base, exp, modulus), BigUint::zero());
assert_eq!(me(base, exp.to_bytes_be(), modulus), BigUint::zero());
// if n % d == 0, then n^m % d == 0
base = BigUint::parse_bytes(b"12345", 10).unwrap();
exp = BigUint::parse_bytes(b"789", 10).unwrap();
modulus = BigUint::parse_bytes(b"15", 10).unwrap();
assert_eq!(me(base, exp, modulus), BigUint::zero());
assert_eq!(me(base, exp.to_bytes_be(), modulus), BigUint::zero());
// others
base = BigUint::parse_bytes(b"12345", 10).unwrap();
exp = BigUint::parse_bytes(b"789", 10).unwrap();
modulus = BigUint::parse_bytes(b"97", 10).unwrap();
assert_eq!(me(base, exp, modulus), BigUint::parse_bytes(b"55", 10).unwrap());
assert_eq!(me(base, exp.to_bytes_be(), modulus), BigUint::parse_bytes(b"55", 10).unwrap());
}
#[test]

View File

@@ -15,7 +15,7 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use bytes::Bytes;
use ethereum_types::H256;
use ethereum_types::{H256, U256};
use transaction::UnverifiedTransaction;
use blockchain::ImportRoute;
use std::time::Duration;
@@ -141,7 +141,15 @@ pub trait ChainNotify : Send + Sync {
}
/// fires when chain broadcasts a message
fn broadcast(&self, _message_type: ChainMessageType) {}
fn broadcast(&self, _message_type: ChainMessageType) {
// does nothing by default
}
/// fires when new block is about to be imported
/// implementations should be light
fn block_pre_import(&self, _bytes: &Bytes, _hash: &H256, _difficulty: &U256) {
// does nothing by default
}
/// fires when new transactions are received from a peer
fn transactions_received(&self,

View File

@@ -32,7 +32,7 @@ use kvdb::{DBValue, KeyValueDB, DBTransaction};
// other
use ethereum_types::{H256, Address, U256};
use block::{IsBlock, LockedBlock, Drain, ClosedBlock, OpenBlock, enact_verified, SealedBlock};
use blockchain::{BlockChain, BlockChainDB, BlockProvider, TreeRoute, ImportRoute, TransactionAddress, ExtrasInsert};
use blockchain::{BlockReceipts, BlockChain, BlockChainDB, BlockProvider, TreeRoute, ImportRoute, TransactionAddress, ExtrasInsert};
use client::ancient_import::AncientVerifier;
use client::{
Nonce, Balance, ChainInfo, BlockInfo, CallContract, TransactionInfo,
@@ -43,7 +43,7 @@ use client::{
};
use client::{
BlockId, TransactionId, UncleId, TraceId, ClientConfig, BlockChainClient,
TraceFilter, CallAnalytics, BlockImportError, Mode,
TraceFilter, CallAnalytics, Mode,
ChainNotify, ChainRoute, PruningInfo, ProvingBlockChainClient, EngineInfo, ChainMessageType,
IoClient, BadBlocks,
};
@@ -51,8 +51,8 @@ use client::bad_blocks;
use encoded;
use engines::{EthEngine, EpochTransition, ForkChoice};
use error::{
ImportErrorKind, BlockImportErrorKind, ExecutionError, CallError, BlockError, ImportResult,
QueueError, QueueErrorKind, Error as EthcoreError, EthcoreResult,
ImportErrorKind, ExecutionError, CallError, BlockError,
QueueError, QueueErrorKind, Error as EthcoreError, EthcoreResult, ErrorKind as EthcoreErrorKind
};
use vm::{EnvInfo, LastHashes};
use evm::Schedule;
@@ -66,7 +66,7 @@ use ethcore_miner::pool::VerifiedTransaction;
use parking_lot::{Mutex, RwLock};
use rand::OsRng;
use receipt::{Receipt, LocalizedReceipt};
use snapshot::{self, io as snapshot_io};
use snapshot::{self, io as snapshot_io, SnapshotClient};
use spec::Spec;
use state_db::StateDB;
use state::{self, State};
@@ -86,7 +86,7 @@ pub use types::block_status::BlockStatus;
pub use blockchain::CacheSize as BlockChainCacheSize;
pub use verification::QueueInfo as BlockQueueInfo;
use_contract!(registry, "Registry", "res/contracts/registrar.json");
use_contract!(registry, "res/contracts/registrar.json");
const MAX_ANCIENT_BLOCKS_QUEUE_SIZE: usize = 4096;
// Max number of blocks imported at once.
@@ -232,8 +232,6 @@ pub struct Client {
/// An action to be done if a mode/spec_name change happens
on_user_defaults_change: Mutex<Option<Box<FnMut(Option<Mode>) + 'static + Send>>>,
/// Link to a registry object useful for looking up names
registrar: registry::Registry,
registrar_address: Option<Address>,
/// A closure to call when we want to restart the client
@@ -264,13 +262,12 @@ impl Importer {
/// This is triggered by a message coming from a block queue when the block is ready for insertion
pub fn import_verified_blocks(&self, client: &Client) -> usize {
// Shortcut out if we know we're incapable of syncing the chain.
if !client.enabled.load(AtomicOrdering::Relaxed) {
return 0;
}
let max_blocks_to_import = 4;
let max_blocks_to_import = client.config.max_round_blocks_to_import;
let (imported_blocks, import_results, invalid_blocks, imported, proposed_blocks, duration, is_empty) = {
let mut imported_blocks = Vec::with_capacity(max_blocks_to_import);
let mut invalid_blocks = HashSet::new();
@@ -476,7 +473,7 @@ impl Importer {
let number = header.number();
let parent = header.parent_hash();
let chain = client.chain.read();
let is_finalized = false;
let mut is_finalized = false;
// Commit results
let block = block.drain();
@@ -484,7 +481,7 @@ impl Importer {
let mut batch = DBTransaction::new();
let ancestry_actions = self.engine.ancestry_actions(&block, &mut chain.ancestry_with_metadata_iter(*parent));
let ancestry_actions = self.engine.ancestry_actions(&header, &mut chain.ancestry_with_metadata_iter(*parent));
let receipts = block.receipts;
let traces = block.traces.drain();
@@ -538,10 +535,18 @@ impl Importer {
state.journal_under(&mut batch, number, hash).expect("DB commit failed");
for ancestry_action in ancestry_actions {
let AncestryAction::MarkFinalized(ancestry) = ancestry_action;
chain.mark_finalized(&mut batch, ancestry).expect("Engine's ancestry action must be known blocks; qed");
}
let finalized: Vec<_> = ancestry_actions.into_iter().map(|ancestry_action| {
let AncestryAction::MarkFinalized(a) = ancestry_action;
if a != header.hash() {
chain.mark_finalized(&mut batch, a).expect("Engine's ancestry action must be known blocks; qed");
} else {
// we're finalizing the current block
is_finalized = true;
}
a
}).collect();
let route = chain.insert_block(&mut batch, block_data, receipts.clone(), ExtrasInsert {
fork_choice: fork_choice,
@@ -562,7 +567,7 @@ impl Importer {
client.db.read().key_value().write_buffered(batch);
chain.commit();
self.check_epoch_end(&header, &chain, client);
self.check_epoch_end(&header, &finalized, &chain, client);
client.update_last_hashes(&parent, hash);
@@ -669,9 +674,10 @@ impl Importer {
}
// check for ending of epoch and write transition if it occurs.
fn check_epoch_end<'a>(&self, header: &'a Header, chain: &BlockChain, client: &Client) {
fn check_epoch_end<'a>(&self, header: &'a Header, finalized: &'a [H256], chain: &BlockChain, client: &Client) {
let is_epoch_end = self.engine.is_epoch_end(
header,
finalized,
&(|hash| client.block_header_decoded(BlockId::Hash(hash))),
&(|hash| chain.get_pending_transition(hash)), // TODO: limit to current epoch.
);
@@ -779,7 +785,6 @@ impl Client {
factories: factories,
history: history,
on_user_defaults_change: Mutex::new(None),
registrar: registry::Registry::default(),
registrar_address,
exit_handler: Mutex::new(None),
importer,
@@ -876,7 +881,7 @@ impl Client {
/// Flush the block import queue.
pub fn flush_queue(&self) {
self.importer.block_queue.flush();
while !self.importer.block_queue.queue_info().is_empty() {
while !self.importer.block_queue.is_empty() {
self.import_verified_blocks();
}
}
@@ -1000,6 +1005,16 @@ impl Client {
self.importer.miner.clone()
}
#[cfg(test)]
pub fn state_db(&self) -> ::parking_lot::RwLockReadGuard<StateDB> {
self.state_db.read()
}
#[cfg(test)]
pub fn chain(&self) -> Arc<BlockChain> {
self.chain.read().clone()
}
/// Replace io channel. Useful for testing.
pub fn set_io_channel(&self, io_channel: IoChannel<ClientIoMessage>) {
*self.io_channel.write() = io_channel;
@@ -1369,17 +1384,17 @@ impl BlockChainTrait for Client {}
impl RegistryInfo for Client {
fn registry_address(&self, name: String, block: BlockId) -> Option<Address> {
use ethabi::FunctionOutputDecoder;
let address = self.registrar_address?;
self.registrar.functions()
.get_address()
.call(keccak(name.as_bytes()), "A", &|data| self.call_contract(block, address, data))
.ok()
.and_then(|a| if a.is_zero() {
None
} else {
Some(a)
})
let (data, decoder) = registry::functions::get_address::call(keccak(name.as_bytes()), "A");
let value = decoder.decode(&self.call_contract(block, address, data).ok()?).ok()?;
if value.is_zero() {
None
} else {
Some(value)
}
}
}
@@ -1398,25 +1413,37 @@ impl CallContract for Client {
}
impl ImportBlock for Client {
fn import_block(&self, unverified: Unverified) -> Result<H256, BlockImportError> {
fn import_block(&self, unverified: Unverified) -> EthcoreResult<H256> {
if self.chain.read().is_known(&unverified.hash()) {
bail!(BlockImportErrorKind::Import(ImportErrorKind::AlreadyInChain));
bail!(EthcoreErrorKind::Import(ImportErrorKind::AlreadyInChain));
}
let status = self.block_status(BlockId::Hash(unverified.parent_hash()));
if status == BlockStatus::Unknown {
bail!(BlockImportErrorKind::Block(BlockError::UnknownParent(unverified.parent_hash())));
bail!(EthcoreErrorKind::Block(BlockError::UnknownParent(unverified.parent_hash())));
}
let raw = unverified.bytes.clone();
match self.importer.block_queue.import(unverified).map_err(Into::into) {
Ok(res) => Ok(res),
// we only care about block errors (not import errors)
Err(BlockImportError(BlockImportErrorKind::Block(err), _))=> {
self.importer.bad_blocks.report(raw, format!("{:?}", err));
bail!(BlockImportErrorKind::Block(err))
let raw = if self.importer.block_queue.is_empty() {
Some((
unverified.bytes.clone(),
unverified.header.hash(),
*unverified.header.difficulty(),
))
} else { None };
match self.importer.block_queue.import(unverified) {
Ok(hash) => {
if let Some((raw, hash, difficulty)) = raw {
self.notify(move |n| n.block_pre_import(&raw, &hash, &difficulty));
}
Ok(hash)
},
Err(e) => Err(e),
// we only care about block errors (not import errors)
Err((block, EthcoreError(EthcoreErrorKind::Block(err), _))) => {
self.importer.bad_blocks.report(block.bytes, format!("{:?}", err));
bail!(EthcoreErrorKind::Block(err))
},
Err((_, e)) => Err(e),
}
}
}
@@ -1795,26 +1822,49 @@ impl BlockChainClient for Client {
}
fn transaction_receipt(&self, id: TransactionId) -> Option<LocalizedReceipt> {
// NOTE Don't use block_receipts here for performance reasons
let address = self.transaction_address(id)?;
let hash = address.block_hash;
let chain = self.chain.read();
self.transaction_address(id)
.and_then(|address| chain.block_number(&address.block_hash).and_then(|block_number| {
let transaction = chain.block_body(&address.block_hash)
.and_then(|body| body.view().localized_transaction_at(&address.block_hash, block_number, address.index));
let number = chain.block_number(&hash)?;
let body = chain.block_body(&hash)?;
let mut receipts = chain.block_receipts(&hash)?.receipts;
receipts.truncate(address.index + 1);
let previous_receipts = (0..address.index + 1)
.map(|index| {
let mut address = address.clone();
address.index = index;
chain.transaction_receipt(&address)
})
.collect();
match (transaction, previous_receipts) {
(Some(transaction), Some(previous_receipts)) => {
Some(transaction_receipt(self.engine().machine(), transaction, previous_receipts))
},
_ => None,
}
}))
let transaction = body.view().localized_transaction_at(&hash, number, address.index)?;
let receipt = receipts.pop()?;
let gas_used = receipts.last().map_or_else(|| 0.into(), |r| r.gas_used);
let no_of_logs = receipts.into_iter().map(|receipt| receipt.logs.len()).sum::<usize>();
let receipt = transaction_receipt(self.engine().machine(), transaction, receipt, gas_used, no_of_logs);
Some(receipt)
}
fn localized_block_receipts(&self, id: BlockId) -> Option<Vec<LocalizedReceipt>> {
let hash = self.block_hash(id)?;
let chain = self.chain.read();
let receipts = chain.block_receipts(&hash)?;
let number = chain.block_number(&hash)?;
let body = chain.block_body(&hash)?;
let engine = self.engine.clone();
let mut gas_used = 0.into();
let mut no_of_logs = 0;
Some(body
.view()
.localized_transactions(&hash, number)
.into_iter()
.zip(receipts.receipts)
.map(move |(transaction, receipt)| {
let result = transaction_receipt(engine.machine(), transaction, receipt, gas_used, no_of_logs);
gas_used = result.cumulative_gas_used;
no_of_logs += result.logs.len();
result
})
.collect()
)
}
fn tree_route(&self, from: &H256, to: &H256) -> Option<TreeRoute> {
@@ -1833,14 +1883,18 @@ impl BlockChainClient for Client {
self.state_db.read().journal_db().state(hash)
}
fn block_receipts(&self, hash: &H256) -> Option<Bytes> {
self.chain.read().block_receipts(hash).map(|receipts| ::rlp::encode(&receipts).into_vec())
fn block_receipts(&self, hash: &H256) -> Option<BlockReceipts> {
self.chain.read().block_receipts(hash)
}
fn queue_info(&self) -> BlockQueueInfo {
self.importer.block_queue.queue_info()
}
fn is_queue_empty(&self) -> bool {
self.importer.block_queue.is_empty()
}
fn clear_queue(&self) {
self.importer.block_queue.clear();
}
@@ -2097,14 +2151,14 @@ impl IoClient for Client {
});
}
fn queue_ancient_block(&self, unverified: Unverified, receipts_bytes: Bytes) -> Result<H256, BlockImportError> {
fn queue_ancient_block(&self, unverified: Unverified, receipts_bytes: Bytes) -> EthcoreResult<H256> {
trace_time!("queue_ancient_block");
let hash = unverified.hash();
{
// check block order
if self.chain.read().is_known(&hash) {
bail!(BlockImportErrorKind::Import(ImportErrorKind::AlreadyInChain));
bail!(EthcoreErrorKind::Import(ImportErrorKind::AlreadyInChain));
}
let parent_hash = unverified.parent_hash();
// NOTE To prevent race condition with import, make sure to check queued blocks first
@@ -2113,7 +2167,7 @@ impl IoClient for Client {
if !is_parent_pending {
let status = self.block_status(BlockId::Hash(parent_hash));
if status == BlockStatus::Unknown {
bail!(BlockImportErrorKind::Block(BlockError::UnknownParent(parent_hash)));
bail!(EthcoreErrorKind::Block(BlockError::UnknownParent(parent_hash)));
}
}
}
@@ -2249,27 +2303,38 @@ impl ScheduleInfo for Client {
}
impl ImportSealedBlock for Client {
fn import_sealed_block(&self, block: SealedBlock) -> ImportResult {
let h = block.header().hash();
fn import_sealed_block(&self, block: SealedBlock) -> EthcoreResult<H256> {
let start = Instant::now();
let raw = block.rlp_bytes();
let header = block.header().clone();
let hash = header.hash();
self.notify(|n| n.block_pre_import(&raw, &hash, header.difficulty()));
let route = {
// Do a super duper basic verification to detect potential bugs
if let Err(e) = self.engine.verify_block_basic(&header) {
self.importer.bad_blocks.report(
block.rlp_bytes(),
format!("Detected an issue with locally sealed block: {}", e),
);
return Err(e.into());
}
// scope for self.import_lock
let _import_lock = self.importer.import_lock.lock();
trace_time!("import_sealed_block");
let number = block.header().number();
let block_data = block.rlp_bytes();
let header = block.header().clone();
let route = self.importer.commit_block(block, &header, encoded::Block::new(block_data), self);
trace!(target: "client", "Imported sealed block #{} ({})", number, h);
trace!(target: "client", "Imported sealed block #{} ({})", header.number(), hash);
self.state_db.write().sync_cache(&route.enacted, &route.retracted, false);
route
};
let route = ChainRoute::from([route].as_ref());
self.importer.miner.chain_new_blocks(
self,
&[h.clone()],
&[hash],
&[],
route.enacted(),
route.retracted(),
@@ -2277,16 +2342,16 @@ impl ImportSealedBlock for Client {
);
self.notify(|notify| {
notify.new_blocks(
vec![h.clone()],
vec![hash],
vec![],
route.clone(),
vec![h.clone()],
vec![hash],
vec![],
start.elapsed(),
);
});
self.db.read().key_value().flush().expect("DB flush failed.");
Ok(h)
Ok(hash)
}
}
@@ -2379,6 +2444,8 @@ impl ProvingBlockChainClient for Client {
}
}
impl SnapshotClient for Client {}
impl Drop for Client {
fn drop(&mut self) {
self.engine.stop();
@@ -2387,16 +2454,14 @@ impl Drop for Client {
/// Returns `LocalizedReceipt` given `LocalizedTransaction`
/// and a vector of receipts from given block up to transaction index.
fn transaction_receipt(machine: &::machine::EthereumMachine, mut tx: LocalizedTransaction, mut receipts: Vec<Receipt>) -> LocalizedReceipt {
assert_eq!(receipts.len(), tx.transaction_index + 1, "All previous receipts are provided.");
fn transaction_receipt(
machine: &::machine::EthereumMachine,
mut tx: LocalizedTransaction,
receipt: Receipt,
prior_gas_used: U256,
prior_no_of_logs: usize,
) -> LocalizedReceipt {
let sender = tx.sender();
let receipt = receipts.pop().expect("Current receipt is provided; qed");
let prior_gas_used = match tx.transaction_index {
0 => 0.into(),
i => receipts.get(i - 1).expect("All previous receipts are provided; qed").gas_used,
};
let no_of_logs = receipts.into_iter().map(|receipt| receipt.logs.len()).sum::<usize>();
let transaction_hash = tx.hash();
let block_hash = tx.block_hash;
let block_number = tx.block_number;
@@ -2425,7 +2490,7 @@ fn transaction_receipt(machine: &::machine::EthereumMachine, mut tx: LocalizedTr
transaction_hash: transaction_hash,
transaction_index: transaction_index,
transaction_log_index: i,
log_index: no_of_logs + i,
log_index: prior_no_of_logs + i,
}).collect(),
log_bloom: receipt.log_bloom,
outcome: receipt.outcome,
@@ -2473,6 +2538,33 @@ mod tests {
assert!(client.tree_route(&genesis, &new_hash).is_none());
}
#[test]
fn should_return_block_receipts() {
use client::{BlockChainClient, BlockId, TransactionId};
use test_helpers::{generate_dummy_client_with_data};
let client = generate_dummy_client_with_data(2, 2, &[1.into(), 1.into()]);
let receipts = client.localized_block_receipts(BlockId::Latest).unwrap();
assert_eq!(receipts.len(), 2);
assert_eq!(receipts[0].transaction_index, 0);
assert_eq!(receipts[0].block_number, 2);
assert_eq!(receipts[0].cumulative_gas_used, 53_000.into());
assert_eq!(receipts[0].gas_used, 53_000.into());
assert_eq!(receipts[1].transaction_index, 1);
assert_eq!(receipts[1].block_number, 2);
assert_eq!(receipts[1].cumulative_gas_used, 106_000.into());
assert_eq!(receipts[1].gas_used, 53_000.into());
let receipt = client.transaction_receipt(TransactionId::Hash(receipts[0].transaction_hash));
assert_eq!(receipt, Some(receipts[0].clone()));
let receipt = client.transaction_receipt(TransactionId::Hash(receipts[1].transaction_hash));
assert_eq!(receipt, Some(receipts[1].clone()));
}
#[test]
fn should_return_correct_log_index() {
use hash::keccak;
@@ -2516,20 +2608,15 @@ mod tests {
topics: vec![],
data: vec![],
}];
let receipts = vec![Receipt {
outcome: TransactionOutcome::StateRoot(state_root),
gas_used: 5.into(),
log_bloom: Default::default(),
logs: vec![logs[0].clone()],
}, Receipt {
let receipt = Receipt {
outcome: TransactionOutcome::StateRoot(state_root),
gas_used: gas_used,
log_bloom: Default::default(),
logs: logs.clone(),
}];
};
// when
let receipt = transaction_receipt(&machine, transaction, receipts);
let receipt = transaction_receipt(&machine, transaction, receipt, 5.into(), 1);
// then
assert_eq!(receipt, LocalizedReceipt {

View File

@@ -121,6 +121,8 @@ pub struct ClientConfig {
pub check_seal: bool,
/// Maximal number of transactions queued for verification in a separate thread.
pub transaction_verification_queue_size: usize,
/// Maximal number of blocks to import at each round.
pub max_round_blocks_to_import: usize,
/// Snapshot configuration
pub snapshot: SnapshotConfiguration,
}
@@ -147,6 +149,7 @@ impl Default for ClientConfig {
history_mem: 32 * mb,
check_seal: true,
transaction_verification_queue_size: 8192,
max_round_blocks_to_import: 12,
snapshot: Default::default(),
}
}

View File

@@ -86,9 +86,9 @@ impl<'a> EvmTestClient<'a> {
ForkSpec::EIP150 => Some(ethereum::new_eip150_test()),
ForkSpec::EIP158 => Some(ethereum::new_eip161_test()),
ForkSpec::Byzantium => Some(ethereum::new_byzantium_test()),
ForkSpec::Constantinople => Some(ethereum::new_constantinople_test()),
ForkSpec::EIP158ToByzantiumAt5 => Some(ethereum::new_transition_test()),
ForkSpec::FrontierToHomesteadAt5 | ForkSpec::HomesteadToDaoAt5 | ForkSpec::HomesteadToEIP150At5 => None,
_ => None,
}
}
@@ -182,6 +182,19 @@ impl<'a> EvmTestClient<'a> {
gas_used: 0.into(),
gas_limit: *genesis.gas_limit(),
};
self.call_envinfo(params, tracer, vm_tracer, info)
}
/// Execute the VM given envinfo, ActionParams and tracer.
/// Returns amount of gas left and the output.
pub fn call_envinfo<T: trace::Tracer, V: trace::VMTracer>(
&mut self,
params: ActionParams,
tracer: &mut T,
vm_tracer: &mut V,
info: client::EnvInfo,
) -> Result<FinalizationResult, EvmTestError>
{
let mut substate = state::Substate::new();
let machine = self.spec.engine.machine();
let schedule = machine.schedule(info.number);

View File

@@ -50,7 +50,7 @@ pub use types::call_analytics::CallAnalytics;
pub use executive::{Executed, Executive, TransactOptions};
pub use vm::{LastHashes, EnvInfo};
pub use error::{BlockImportError, BlockImportErrorKind, TransactionImportError};
pub use error::TransactionImportError;
pub use verification::VerifierType;
mod traits;

View File

@@ -37,7 +37,7 @@ use blockchain::{TreeRoute, BlockReceipts};
use client::{
Nonce, Balance, ChainInfo, BlockInfo, ReopenBlock, CallContract, TransactionInfo, RegistryInfo,
PrepareOpenBlock, BlockChainClient, BlockChainInfo, BlockStatus, BlockId, Mode,
TransactionId, UncleId, TraceId, TraceFilter, LastHashes, CallAnalytics, BlockImportError,
TransactionId, UncleId, TraceId, TraceFilter, LastHashes, CallAnalytics,
ProvingBlockChainClient, ScheduleInfo, ImportSealedBlock, BroadcastProposalBlock, ImportBlock, StateOrBlock,
Call, StateClient, EngineInfo, AccountData, BlockChain, BlockProducer, SealedBlockImporter, IoClient,
BadBlocks,
@@ -47,7 +47,7 @@ use header::{Header as BlockHeader, BlockNumber};
use filter::Filter;
use log_entry::LocalizedLogEntry;
use receipt::{Receipt, LocalizedReceipt, TransactionOutcome};
use error::{Error, ImportResult};
use error::{Error, EthcoreResult};
use vm::Schedule;
use miner::{self, Miner, MinerService};
use spec::Spec;
@@ -415,7 +415,7 @@ impl ScheduleInfo for TestBlockChainClient {
}
impl ImportSealedBlock for TestBlockChainClient {
fn import_sealed_block(&self, _block: SealedBlock) -> ImportResult {
fn import_sealed_block(&self, _block: SealedBlock) -> EthcoreResult<H256> {
Ok(H256::default())
}
}
@@ -522,7 +522,7 @@ impl RegistryInfo for TestBlockChainClient {
}
impl ImportBlock for TestBlockChainClient {
fn import_block(&self, unverified: Unverified) -> Result<H256, BlockImportError> {
fn import_block(&self, unverified: Unverified) -> EthcoreResult<H256> {
let header = unverified.header;
let h = header.hash();
let number: usize = header.number() as usize;
@@ -686,6 +686,10 @@ impl BlockChainClient for TestBlockChainClient {
self.receipts.read().get(&id).cloned()
}
fn localized_block_receipts(&self, _id: BlockId) -> Option<Vec<LocalizedReceipt>> {
Some(self.receipts.read().values().cloned().collect())
}
fn logs(&self, filter: Filter) -> Result<Vec<LocalizedLogEntry>, BlockId> {
match self.error_on_logs.read().as_ref() {
Some(id) => return Err(id.clone()),
@@ -785,16 +789,14 @@ impl BlockChainClient for TestBlockChainClient {
None
}
fn block_receipts(&self, hash: &H256) -> Option<Bytes> {
fn block_receipts(&self, hash: &H256) -> Option<BlockReceipts> {
// starts with 'f' ?
if *hash > H256::from("f000000000000000000000000000000000000000000000000000000000000000") {
let receipt = BlockReceipts::new(vec![Receipt::new(
TransactionOutcome::StateRoot(H256::zero()),
U256::zero(),
vec![])]);
let mut rlp = RlpStream::new();
rlp.append(&receipt);
return Some(rlp.out());
return Some(receipt);
}
None
}
@@ -882,7 +884,7 @@ impl IoClient for TestBlockChainClient {
self.miner.import_external_transactions(self, txs);
}
fn queue_ancient_block(&self, unverified: Unverified, _r: Bytes) -> Result<H256, BlockImportError> {
fn queue_ancient_block(&self, unverified: Unverified, _r: Bytes) -> EthcoreResult<H256> {
self.import_block(unverified)
}

View File

@@ -20,11 +20,11 @@ use std::sync::Arc;
use itertools::Itertools;
use block::{OpenBlock, SealedBlock, ClosedBlock};
use blockchain::TreeRoute;
use blockchain::{BlockReceipts, TreeRoute};
use client::Mode;
use encoded;
use vm::LastHashes;
use error::{Error, ImportResult, CallError, BlockImportError};
use error::{Error, CallError, EthcoreResult};
use evm::Schedule;
use executive::Executed;
use filter::Filter;
@@ -42,7 +42,7 @@ use engines::EthEngine;
use ethereum_types::{H256, U256, Address};
use ethcore_miner::pool::VerifiedTransaction;
use bytes::Bytes;
use hashdb::DBValue;
use kvdb::DBValue;
use types::ids::*;
use types::basic_account::BasicAccount;
@@ -168,7 +168,7 @@ pub trait RegistryInfo {
/// Provides methods to import block into blockchain
pub trait ImportBlock {
/// Import a block into the blockchain.
fn import_block(&self, block: Unverified) -> Result<H256, BlockImportError>;
fn import_block(&self, block: Unverified) -> EthcoreResult<H256>;
}
/// Provides `call_contract` method
@@ -205,7 +205,7 @@ pub trait IoClient: Sync + Send {
fn queue_transactions(&self, transactions: Vec<Bytes>, peer_id: usize);
/// Queue block import with transaction receipts. Does no sealing and transaction validation.
fn queue_ancient_block(&self, block_bytes: Unverified, receipts_bytes: Bytes) -> Result<H256, BlockImportError>;
fn queue_ancient_block(&self, block_bytes: Unverified, receipts_bytes: Bytes) -> EthcoreResult<H256>;
/// Queue conensus engine message.
fn queue_consensus_message(&self, message: Bytes);
@@ -281,6 +281,9 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra
/// Get transaction receipt with given hash.
fn transaction_receipt(&self, id: TransactionId) -> Option<LocalizedReceipt>;
/// Get localized receipts for all transaction in given block.
fn localized_block_receipts(&self, id: BlockId) -> Option<Vec<LocalizedReceipt>>;
/// Get a tree route between `from` and `to`.
/// See `BlockChain::tree_route`.
fn tree_route(&self, from: &H256, to: &H256) -> Option<TreeRoute>;
@@ -291,12 +294,17 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra
/// Get latest state node
fn state_data(&self, hash: &H256) -> Option<Bytes>;
/// Get raw block receipts data by block header hash.
fn block_receipts(&self, hash: &H256) -> Option<Bytes>;
/// Get block receipts data by block header hash.
fn block_receipts(&self, hash: &H256) -> Option<BlockReceipts>;
/// Get block queue information.
fn queue_info(&self) -> BlockQueueInfo;
/// Returns true if block queue is empty.
fn is_queue_empty(&self) -> bool {
self.queue_info().is_empty()
}
/// Clear block queue and abort all import activity.
fn clear_queue(&self);
@@ -414,7 +422,7 @@ pub trait ScheduleInfo {
///Provides `import_sealed_block` method
pub trait ImportSealedBlock {
/// Import sealed block. Skips all verifications.
fn import_sealed_block(&self, block: SealedBlock) -> ImportResult;
fn import_sealed_block(&self, block: SealedBlock) -> EthcoreResult<H256>;
}
/// Provides `broadcast_proposal_block` method

View File

@@ -96,7 +96,10 @@ impl RollingFinality {
}
/// Get an iterator over stored hashes in order.
pub fn unfinalized_hashes(&self) -> Iter { Iter(self.headers.iter()) }
#[cfg(test)]
pub fn unfinalized_hashes(&self) -> impl Iterator<Item=&H256> {
self.headers.iter().map(|(h, _)| h)
}
/// Get the validator set.
pub fn validators(&self) -> &SimpleList { &self.signers }
@@ -145,16 +148,6 @@ impl RollingFinality {
}
}
pub struct Iter<'a>(::std::collections::vec_deque::Iter<'a, (H256, Vec<Address>)>);
impl<'a> Iterator for Iter<'a> {
type Item = H256;
fn next(&mut self) -> Option<H256> {
self.0.next().map(|&(h, _)| h)
}
}
#[cfg(test)]
mod tests {
use ethereum_types::{H256, Address};
@@ -220,7 +213,7 @@ mod tests {
// only the last hash has < 51% of authorities' signatures
assert_eq!(finality.unfinalized_hashes().count(), 1);
assert_eq!(finality.unfinalized_hashes().next(), Some(hashes[11].0));
assert_eq!(finality.unfinalized_hashes().next(), Some(&hashes[11].0));
assert_eq!(finality.subchain_head(), Some(hashes[11].0));
}
}

View File

@@ -16,8 +16,8 @@
//! A blockchain engine that supports a non-instant BFT proof-of-authority.
use std::collections::{BTreeMap, HashSet};
use std::fmt;
use std::collections::{BTreeMap, BTreeSet, HashSet};
use std::{cmp, fmt};
use std::iter::FromIterator;
use std::ops::Deref;
use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering};
@@ -44,6 +44,7 @@ use itertools::{self, Itertools};
use rlp::{encode, Decodable, DecoderError, Encodable, RlpStream, Rlp};
use ethereum_types::{H256, H520, Address, U128, U256};
use parking_lot::{Mutex, RwLock};
use types::ancestry_action::AncestryAction;
use unexpected::{Mismatch, OutOfBounds};
mod finality;
@@ -122,10 +123,10 @@ struct Step {
}
impl Step {
fn load(&self) -> usize { self.inner.load(AtomicOrdering::SeqCst) }
fn load(&self) -> u64 { self.inner.load(AtomicOrdering::SeqCst) as u64 }
fn duration_remaining(&self) -> Duration {
let now = unix_now();
let expected_seconds = (self.load() as u64)
let expected_seconds = self.load()
.checked_add(1)
.and_then(|ctr| ctr.checked_mul(self.duration as u64))
.map(Duration::from_secs);
@@ -161,8 +162,8 @@ impl Step {
}
}
fn check_future(&self, given: usize) -> Result<(), Option<OutOfBounds<u64>>> {
const REJECTED_STEP_DRIFT: usize = 4;
fn check_future(&self, given: u64) -> Result<(), Option<OutOfBounds<u64>>> {
const REJECTED_STEP_DRIFT: u64 = 4;
// Verify if the step is correct.
if given <= self.load() {
@@ -181,8 +182,8 @@ impl Step {
let d = self.duration as u64;
Err(Some(OutOfBounds {
min: None,
max: Some(d * current as u64),
found: d * given as u64,
max: Some(d * current),
found: d * given,
}))
} else {
Ok(())
@@ -191,8 +192,8 @@ impl Step {
}
// Chain scoring: total weight is sqrt(U256::max_value())*height - step
fn calculate_score(parent_step: U256, current_step: U256, current_empty_steps: U256) -> U256 {
U256::from(U128::max_value()) + parent_step - current_step + current_empty_steps
fn calculate_score(parent_step: u64, current_step: u64, current_empty_steps: usize) -> U256 {
U256::from(U128::max_value()) + U256::from(parent_step) - U256::from(current_step) + U256::from(current_empty_steps)
}
struct EpochManager {
@@ -214,7 +215,7 @@ impl EpochManager {
// zoom to epoch for given header. returns true if succeeded, false otherwise.
fn zoom_to(&mut self, client: &EngineClient, machine: &EthereumMachine, validators: &ValidatorSet, header: &Header) -> bool {
let last_was_parent = self.finality_checker.subchain_head() == Some(header.parent_hash().clone());
let last_was_parent = self.finality_checker.subchain_head() == Some(*header.parent_hash());
// early exit for current target == chain head, but only if the epochs are
// the same.
@@ -283,13 +284,26 @@ impl EpochManager {
/// A message broadcast by authorities when it's their turn to seal a block but there are no
/// transactions. Other authorities accumulate these messages and later include them in the seal as
/// proof.
#[derive(Clone, Debug)]
#[derive(Clone, Debug, PartialEq, Eq)]
struct EmptyStep {
signature: H520,
step: usize,
step: u64,
parent_hash: H256,
}
impl PartialOrd for EmptyStep {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for EmptyStep {
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.step.cmp(&other.step)
.then_with(|| self.parent_hash.cmp(&other.parent_hash))
.then_with(|| self.signature.cmp(&other.signature))
}
}
impl EmptyStep {
fn from_sealed(sealed_empty_step: SealedEmptyStep, parent_hash: &H256) -> EmptyStep {
let signature = sealed_empty_step.signature;
@@ -352,7 +366,7 @@ pub fn empty_step_full_rlp(signature: &H520, empty_step_rlp: &[u8]) -> Vec<u8> {
s.out()
}
pub fn empty_step_rlp(step: usize, parent_hash: &H256) -> Vec<u8> {
pub fn empty_step_rlp(step: u64, parent_hash: &H256) -> Vec<u8> {
let mut s = RlpStream::new_list(2);
s.append(&step).append(parent_hash);
s.out()
@@ -364,7 +378,7 @@ pub fn empty_step_rlp(step: usize, parent_hash: &H256) -> Vec<u8> {
/// empty message is included.
struct SealedEmptyStep {
signature: H520,
step: usize,
step: u64,
}
impl Encodable for SealedEmptyStep {
@@ -398,7 +412,7 @@ pub struct AuthorityRound {
validators: Box<ValidatorSet>,
validate_score_transition: u64,
validate_step_transition: u64,
empty_steps: Mutex<Vec<EmptyStep>>,
empty_steps: Mutex<BTreeSet<EmptyStep>>,
epoch_manager: Mutex<EpochManager>,
immediate_transitions: bool,
block_reward: U256,
@@ -451,7 +465,7 @@ impl super::EpochVerifier<EthereumMachine> for EpochVerifier {
Some(header) => header_empty_steps_signers(header, self.empty_steps_transition).ok()?,
_ => Vec::new(),
};
signers.push(parent_header.author().clone());
signers.push(*parent_header.author());
let newly_finalized = finality_checker.push_hash(parent_header.hash(), signers).ok()?;
finalized.extend(newly_finalized);
@@ -493,7 +507,7 @@ fn header_expected_seal_fields(header: &Header, empty_steps_transition: u64) ->
}
}
fn header_step(header: &Header, empty_steps_transition: u64) -> Result<usize, ::rlp::DecoderError> {
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()
@@ -532,17 +546,17 @@ fn header_empty_steps_signers(header: &Header, empty_steps_transition: u64) -> R
}
}
fn step_proposer(validators: &ValidatorSet, bh: &H256, step: usize) -> Address {
let proposer = validators.get(bh, step);
fn step_proposer(validators: &ValidatorSet, bh: &H256, step: u64) -> Address {
let proposer = validators.get(bh, step as usize);
trace!(target: "engine", "Fetched proposer for step {}: {}", step, proposer);
proposer
}
fn is_step_proposer(validators: &ValidatorSet, bh: &H256, step: usize, address: &Address) -> bool {
fn is_step_proposer(validators: &ValidatorSet, bh: &H256, step: u64, address: &Address) -> bool {
step_proposer(validators, bh, step) == *address
}
fn verify_timestamp(step: &Step, header_step: usize) -> Result<(), BlockError> {
fn verify_timestamp(step: &Step, header_step: u64) -> Result<(), BlockError> {
match step.check_future(header_step) {
Err(None) => {
trace!(target: "engine", "verify_timestamp: block from the future");
@@ -563,7 +577,7 @@ fn verify_external(header: &Header, validators: &ValidatorSet, empty_steps_trans
let header_step = header_step(header, empty_steps_transition)?;
let proposer_signature = header_signature(header, empty_steps_transition)?;
let correct_proposer = validators.get(header.parent_hash(), header_step);
let correct_proposer = validators.get(header.parent_hash(), header_step as usize);
let is_invalid_proposer = *header.author() != correct_proposer || {
let empty_steps_rlp = if header.number() >= empty_steps_transition {
Some(header_empty_steps_raw(header))
@@ -577,7 +591,7 @@ fn verify_external(header: &Header, validators: &ValidatorSet, empty_steps_trans
if is_invalid_proposer {
trace!(target: "engine", "verify_block_external: bad proposer for step: {}", header_step);
Err(EngineError::NotProposer(Mismatch { expected: correct_proposer, found: header.author().clone() }))?
Err(EngineError::NotProposer(Mismatch { expected: correct_proposer, found: *header.author() }))?
} else {
Ok(())
}
@@ -633,13 +647,13 @@ impl AuthorityRound {
panic!("authority_round: step duration can't be zero")
}
let should_timeout = our_params.start_step.is_none();
let initial_step = our_params.start_step.unwrap_or_else(|| (unix_now().as_secs() / (our_params.step_duration as u64))) as usize;
let initial_step = our_params.start_step.unwrap_or_else(|| (unix_now().as_secs() / (our_params.step_duration as u64)));
let engine = Arc::new(
AuthorityRound {
transition_service: IoService::<()>::start()?,
step: Arc::new(PermissionedStep {
inner: Step {
inner: AtomicUsize::new(initial_step),
inner: AtomicUsize::new(initial_step as usize),
calibrate: our_params.start_step.is_none(),
duration: our_params.step_duration,
},
@@ -650,7 +664,7 @@ impl AuthorityRound {
validators: our_params.validators,
validate_score_transition: our_params.validate_score_transition,
validate_step_transition: our_params.validate_step_transition,
empty_steps: Mutex::new(Vec::new()),
empty_steps: Default::default(),
epoch_manager: Mutex::new(EpochManager::blank()),
immediate_transitions: our_params.immediate_transitions,
block_reward: our_params.block_reward,
@@ -698,22 +712,41 @@ impl AuthorityRound {
})
}
fn empty_steps(&self, from_step: U256, to_step: U256, parent_hash: H256) -> Vec<EmptyStep> {
self.empty_steps.lock().iter().filter(|e| {
U256::from(e.step) > from_step &&
U256::from(e.step) < to_step &&
e.parent_hash == parent_hash
}).cloned().collect()
fn empty_steps(&self, from_step: u64, to_step: u64, parent_hash: H256) -> Vec<EmptyStep> {
let from = EmptyStep {
step: from_step + 1,
parent_hash,
signature: Default::default(),
};
let to = EmptyStep {
step: to_step,
parent_hash: Default::default(),
signature: Default::default(),
};
if from >= to {
return vec![];
}
self.empty_steps.lock()
.range(from..to)
.filter(|e| e.parent_hash == parent_hash)
.cloned()
.collect()
}
fn clear_empty_steps(&self, step: U256) {
fn clear_empty_steps(&self, step: u64) {
// clear old `empty_steps` messages
self.empty_steps.lock().retain(|e| U256::from(e.step) > step);
let mut empty_steps = self.empty_steps.lock();
*empty_steps = empty_steps.split_off(&EmptyStep {
step: step + 1,
parent_hash: Default::default(),
signature: Default::default(),
});
}
fn handle_empty_step_message(&self, empty_step: EmptyStep) {
let mut empty_steps = self.empty_steps.lock();
empty_steps.push(empty_step);
self.empty_steps.lock().insert(empty_step);
}
fn generate_empty_step(&self, parent_hash: &H256) {
@@ -743,7 +776,7 @@ impl AuthorityRound {
}
}
fn report_skipped(&self, header: &Header, current_step: usize, parent_step: usize, validators: &ValidatorSet, set_number: u64) {
fn report_skipped(&self, header: &Header, current_step: u64, parent_step: u64, validators: &ValidatorSet, set_number: u64) {
// we're building on top of the genesis block so don't report any skipped steps
if header.number() == 1 {
return;
@@ -764,6 +797,69 @@ impl AuthorityRound {
}
}
}
// Returns the hashes of all ancestor blocks that are finalized by the given `chain_head`.
fn build_finality(&self, chain_head: &Header, ancestry: &mut Iterator<Item=Header>) -> Vec<H256> {
if self.immediate_transitions { return Vec::new() }
let client = match self.client.read().as_ref().and_then(|weak| weak.upgrade()) {
Some(client) => client,
None => {
warn!(target: "engine", "Unable to apply ancestry actions: missing client ref.");
return Vec::new();
}
};
let mut epoch_manager = self.epoch_manager.lock();
if !epoch_manager.zoom_to(&*client, &self.machine, &*self.validators, chain_head) {
return Vec::new();
}
if epoch_manager.finality_checker.subchain_head() != Some(*chain_head.parent_hash()) {
// build new finality checker from unfinalized ancestry of chain head, not including chain head itself yet.
trace!(target: "finality", "Building finality up to parent of {} ({})",
chain_head.hash(), chain_head.parent_hash());
// the empty steps messages in a header signal approval of the
// parent header.
let mut parent_empty_steps_signers = match header_empty_steps_signers(&chain_head, self.empty_steps_transition) {
Ok(empty_step_signers) => empty_step_signers,
Err(_) => {
warn!(target: "finality", "Failed to get empty step signatures from block {}", chain_head.hash());
return Vec::new();
}
};
let epoch_transition_hash = epoch_manager.epoch_transition_hash;
let ancestry_iter = ancestry.map(|header| {
let mut signers = vec![*header.author()];
signers.extend(parent_empty_steps_signers.drain(..));
if let Ok(empty_step_signers) = header_empty_steps_signers(&header, self.empty_steps_transition) {
let res = (header.hash(), signers);
trace!(target: "finality", "Ancestry iteration: yielding {:?}", res);
parent_empty_steps_signers = empty_step_signers;
Some(res)
} else {
warn!(target: "finality", "Failed to get empty step signatures from block {}", header.hash());
None
}
})
.while_some()
.take_while(|&(h, _)| h != epoch_transition_hash);
if let Err(e) = epoch_manager.finality_checker.build_ancestry_subchain(ancestry_iter) {
debug!(target: "engine", "inconsistent validator set within epoch: {:?}", e);
return Vec::new();
}
}
let finalized = epoch_manager.finality_checker.push_hash(chain_head.hash(), vec![*chain_head.author()]);
finalized.unwrap_or_default()
}
}
fn unix_now() -> Duration {
@@ -873,12 +969,12 @@ impl Engine<EthereumMachine> for AuthorityRound {
let current_step = self.step.inner.load();
let current_empty_steps_len = if header.number() >= self.empty_steps_transition {
self.empty_steps(parent_step.into(), current_step.into(), parent.hash()).len()
self.empty_steps(parent_step, current_step, parent.hash()).len()
} else {
0
};
let score = calculate_score(parent_step.into(), current_step.into(), current_empty_steps_len.into());
let score = calculate_score(parent_step, current_step, current_empty_steps_len);
header.set_difficulty(score);
}
@@ -922,8 +1018,8 @@ impl Engine<EthereumMachine> for AuthorityRound {
}
let header = block.header();
let parent_step: U256 = header_step(parent, self.empty_steps_transition)
.expect("Header has been verified; qed").into();
let parent_step = header_step(parent, self.empty_steps_transition)
.expect("Header has been verified; qed");
let step = self.step.inner.load();
@@ -958,7 +1054,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
if is_step_proposer(&*validators, header.parent_hash(), step, header.author()) {
// this is guarded against by `can_propose` unless the block was signed
// on the same step (implies same key) and on a different node.
if parent_step == step.into() {
if parent_step == step {
warn!("Attempted to seal block on the same step as parent. Is this authority sealing with more than one node?");
return Seal::None;
}
@@ -970,13 +1066,16 @@ impl Engine<EthereumMachine> for AuthorityRound {
block.transactions().is_empty() &&
empty_steps.len() < self.maximum_empty_steps {
self.generate_empty_step(header.parent_hash());
if self.step.can_propose.compare_and_swap(true, false, AtomicOrdering::SeqCst) {
self.generate_empty_step(header.parent_hash());
}
return Seal::None;
}
let empty_steps_rlp = if header.number() >= self.empty_steps_transition {
let empty_steps: Vec<_> = empty_steps.iter().map(|e| e.sealed()).collect();
Some(::rlp::encode_list(&empty_steps).into_vec())
Some(::rlp::encode_list(&empty_steps))
} else {
None
};
@@ -994,12 +1093,12 @@ impl Engine<EthereumMachine> for AuthorityRound {
// report any skipped primaries between the parent block and
// the block we're sealing, unless we have empty steps enabled
if header.number() < self.empty_steps_transition {
self.report_skipped(header, step, u64::from(parent_step) as usize, &*validators, set_number);
self.report_skipped(header, step, parent_step, &*validators, set_number);
}
let mut fields = vec![
encode(&step).into_vec(),
encode(&(&H520::from(signature) as &[u8])).into_vec(),
encode(&step),
encode(&(&H520::from(signature) as &[u8])),
];
if let Some(empty_steps_rlp) = empty_steps_rlp {
@@ -1144,7 +1243,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
trace!(target: "engine", "Multiple blocks proposed for step {}.", parent_step);
self.validators.report_malicious(header.author(), set_number, header.number(), Default::default());
Err(EngineError::DoubleVote(header.author().clone()))?;
Err(EngineError::DoubleVote(*header.author()))?;
}
// If empty step messages are enabled we will validate the messages in the seal, missing messages are not
@@ -1230,9 +1329,53 @@ impl Engine<EthereumMachine> for AuthorityRound {
self.validators.signals_epoch_end(first, header, aux)
}
fn is_epoch_end_light(
&self,
chain_head: &Header,
chain: &super::Headers<Header>,
transition_store: &super::PendingTransitionStore,
) -> Option<Vec<u8>> {
// epochs only matter if we want to support light clients.
if self.immediate_transitions { return None }
let epoch_transition_hash = {
let client = match self.client.read().as_ref().and_then(|weak| weak.upgrade()) {
Some(client) => client,
None => {
warn!(target: "engine", "Unable to check for epoch end: missing client ref.");
return None;
}
};
let mut epoch_manager = self.epoch_manager.lock();
if !epoch_manager.zoom_to(&*client, &self.machine, &*self.validators, chain_head) {
return None;
}
epoch_manager.epoch_transition_hash
};
let mut hash = *chain_head.parent_hash();
let mut ancestry = itertools::repeat_call(move || {
chain(hash).and_then(|header| {
if header.number() == 0 { return None }
hash = *header.parent_hash();
Some(header)
})
})
.while_some()
.take_while(|header| header.hash() != epoch_transition_hash);
let finalized = self.build_finality(chain_head, &mut ancestry);
self.is_epoch_end(chain_head, &finalized, chain, transition_store)
}
fn is_epoch_end(
&self,
chain_head: &Header,
finalized: &[H256],
chain: &super::Headers<Header>,
transition_store: &super::PendingTransitionStore,
) -> Option<Vec<u8>> {
@@ -1247,108 +1390,46 @@ impl Engine<EthereumMachine> for AuthorityRound {
return Some(change)
}
let client = match self.client.read().as_ref().and_then(|weak| weak.upgrade()) {
Some(client) => client,
None => {
warn!(target: "engine", "Unable to check for epoch end: missing client ref.");
return None;
}
};
// find most recently finalized blocks, then check transition store for pending transitions.
let mut epoch_manager = self.epoch_manager.lock();
if !epoch_manager.zoom_to(&*client, &self.machine, &*self.validators, chain_head) {
return None;
}
if epoch_manager.finality_checker.subchain_head() != Some(*chain_head.parent_hash()) {
// build new finality checker from ancestry of chain head,
// not including chain head itself yet.
trace!(target: "finality", "Building finality up to parent of {} ({})",
chain_head.hash(), chain_head.parent_hash());
let mut hash = chain_head.parent_hash().clone();
let mut parent_empty_steps_signers = match header_empty_steps_signers(&chain_head, self.empty_steps_transition) {
Ok(empty_step_signers) => empty_step_signers,
Err(_) => {
warn!(target: "finality", "Failed to get empty step signatures from block {}", chain_head.hash());
return None;
}
};
let epoch_transition_hash = epoch_manager.epoch_transition_hash;
// walk the chain within current epoch backwards.
// author == ec_recover(sig) known since the blocks are in the DB.
// the empty steps messages in a header signal approval of the parent header.
let ancestry_iter = itertools::repeat_call(move || {
chain(hash).and_then(|header| {
if header.number() == 0 { return None }
let mut signers = vec![header.author().clone()];
signers.extend(parent_empty_steps_signers.drain(..));
if let Ok(empty_step_signers) = header_empty_steps_signers(&header, self.empty_steps_transition) {
let res = (hash, signers);
trace!(target: "finality", "Ancestry iteration: yielding {:?}", res);
hash = header.parent_hash().clone();
parent_empty_steps_signers = empty_step_signers;
Some(res)
} else {
warn!(target: "finality", "Failed to get empty step signatures from block {}", header.hash());
None
}
// check transition store for pending transitions against recently finalized blocks
for finalized_hash in finalized {
if let Some(pending) = transition_store(*finalized_hash) {
// walk the chain backwards from current head until finalized_hash
// to construct transition proof. author == ec_recover(sig) known
// since the blocks are in the DB.
let mut hash = chain_head.hash();
let mut finality_proof: Vec<_> = itertools::repeat_call(move || {
chain(hash).and_then(|header| {
hash = *header.parent_hash();
if header.number() == 0 { return None }
else { return Some(header) }
})
})
})
.while_some()
.take_while(|&(h, _)| h != epoch_transition_hash);
.while_some()
.take_while(|h| h.hash() != *finalized_hash)
.collect();
if let Err(_) = epoch_manager.finality_checker.build_ancestry_subchain(ancestry_iter) {
debug!(target: "engine", "inconsistent validator set within epoch");
return None;
}
}
let finalized_header = chain(*finalized_hash)
.expect("header is finalized; finalized headers must exist in the chain; qed");
{
if let Ok(finalized) = epoch_manager.finality_checker.push_hash(chain_head.hash(), vec![chain_head.author().clone()]) {
let mut finalized = finalized.into_iter();
while let Some(finalized_hash) = finalized.next() {
if let Some(pending) = transition_store(finalized_hash) {
let finality_proof = ::std::iter::once(finalized_hash)
.chain(finalized)
.chain(epoch_manager.finality_checker.unfinalized_hashes())
.map(|h| if h == chain_head.hash() {
// chain closure only stores ancestry, but the chain head is also
// unfinalized.
chain_head.clone()
} else {
chain(h).expect("these headers fetched before when constructing finality checker; qed")
})
.collect::<Vec<Header>>();
let signal_number = finalized_header.number();
info!(target: "engine", "Applying validator set change signalled at block {}", signal_number);
// this gives us the block number for `hash`, assuming it's ancestry.
let signal_number = chain_head.number()
- finality_proof.len() as BlockNumber
+ 1;
let finality_proof = ::rlp::encode_list(&finality_proof);
epoch_manager.note_new_epoch();
finality_proof.push(finalized_header);
finality_proof.reverse();
info!(target: "engine", "Applying validator set change signalled at block {}", signal_number);
let finality_proof = ::rlp::encode_list(&finality_proof);
// We turn off can_propose here because upon validator set change there can
// be two valid proposers for a single step: one from the old set and
// one from the new.
//
// This way, upon encountering an epoch change, the proposer from the
// new set will be forced to wait until the next step to avoid sealing a
// block that breaks the invariant that the parent's step < the block's step.
self.step.can_propose.store(false, AtomicOrdering::SeqCst);
return Some(combine_proofs(signal_number, &pending.proof, &*finality_proof));
}
}
self.epoch_manager.lock().note_new_epoch();
// We turn off can_propose here because upon validator set change there can
// be two valid proposers for a single step: one from the old set and
// one from the new.
//
// This way, upon encountering an epoch change, the proposer from the
// new set will be forced to wait until the next step to avoid sealing a
// block that breaks the invariant that the parent's step < the block's step.
self.step.can_propose.store(false, AtomicOrdering::SeqCst);
return Some(combine_proofs(signal_number, &pending.proof, &*finality_proof));
}
}
@@ -1403,6 +1484,19 @@ impl Engine<EthereumMachine> for AuthorityRound {
fn fork_choice(&self, new: &ExtendedHeader, current: &ExtendedHeader) -> super::ForkChoice {
super::total_difficulty_fork_choice(new, current)
}
fn ancestry_actions(&self, header: &Header, ancestry: &mut Iterator<Item=ExtendedHeader>) -> Vec<AncestryAction> {
let finalized = self.build_finality(
header,
&mut ancestry.take_while(|e| !e.is_finalized).map(|e| e.header),
);
if !finalized.is_empty() {
debug!(target: "finality", "Finalizing blocks: {:?}", finalized);
}
finalized.into_iter().map(AncestryAction::MarkFinalized).collect()
}
}
#[cfg(test)]
@@ -1446,7 +1540,7 @@ mod tests {
fn can_do_signature_verification_fail() {
let engine = Spec::new_test_round().engine;
let mut header: Header = Header::default();
header.set_seal(vec![encode(&H520::default()).into_vec()]);
header.set_seal(vec![encode(&H520::default())]);
let verify_result = engine.verify_block_external(&header);
assert!(verify_result.is_err());
@@ -1523,7 +1617,7 @@ mod tests {
let tap = AccountProvider::transient_provider();
let addr = tap.insert_account(keccak("0").into(), &"0".into()).unwrap();
let mut parent_header: Header = Header::default();
parent_header.set_seal(vec![encode(&0usize).into_vec()]);
parent_header.set_seal(vec![encode(&0usize)]);
parent_header.set_gas_limit("222222".parse::<U256>().unwrap());
let mut header: Header = Header::default();
header.set_number(1);
@@ -1534,14 +1628,14 @@ mod tests {
// Two validators.
// Spec starts with step 2.
header.set_difficulty(calculate_score(U256::from(0), U256::from(2), U256::zero()));
header.set_difficulty(calculate_score(0, 2, 0));
let signature = tap.sign(addr, Some("0".into()), header.bare_hash()).unwrap();
header.set_seal(vec![encode(&2usize).into_vec(), encode(&(&*signature as &[u8])).into_vec()]);
header.set_seal(vec![encode(&2usize), encode(&(&*signature as &[u8]))]);
assert!(engine.verify_block_family(&header, &parent_header).is_ok());
assert!(engine.verify_block_external(&header).is_err());
header.set_difficulty(calculate_score(U256::from(0), U256::from(1), U256::zero()));
header.set_difficulty(calculate_score(0, 1, 0));
let signature = tap.sign(addr, Some("0".into()), header.bare_hash()).unwrap();
header.set_seal(vec![encode(&1usize).into_vec(), encode(&(&*signature as &[u8])).into_vec()]);
header.set_seal(vec![encode(&1usize), encode(&(&*signature as &[u8]))]);
assert!(engine.verify_block_family(&header, &parent_header).is_ok());
assert!(engine.verify_block_external(&header).is_ok());
}
@@ -1552,7 +1646,7 @@ mod tests {
let addr = tap.insert_account(keccak("0").into(), &"0".into()).unwrap();
let mut parent_header: Header = Header::default();
parent_header.set_seal(vec![encode(&0usize).into_vec()]);
parent_header.set_seal(vec![encode(&0usize)]);
parent_header.set_gas_limit("222222".parse::<U256>().unwrap());
let mut header: Header = Header::default();
header.set_number(1);
@@ -1563,12 +1657,12 @@ mod tests {
// Two validators.
// Spec starts with step 2.
header.set_difficulty(calculate_score(U256::from(0), U256::from(1), U256::zero()));
header.set_difficulty(calculate_score(0, 1, 0));
let signature = tap.sign(addr, Some("0".into()), header.bare_hash()).unwrap();
header.set_seal(vec![encode(&1usize).into_vec(), encode(&(&*signature as &[u8])).into_vec()]);
header.set_seal(vec![encode(&1usize), encode(&(&*signature as &[u8]))]);
assert!(engine.verify_block_family(&header, &parent_header).is_ok());
assert!(engine.verify_block_external(&header).is_ok());
header.set_seal(vec![encode(&5usize).into_vec(), encode(&(&*signature as &[u8])).into_vec()]);
header.set_seal(vec![encode(&5usize), encode(&(&*signature as &[u8]))]);
assert!(engine.verify_block_basic(&header).is_err());
}
@@ -1578,7 +1672,7 @@ mod tests {
let addr = tap.insert_account(keccak("0").into(), &"0".into()).unwrap();
let mut parent_header: Header = Header::default();
parent_header.set_seal(vec![encode(&4usize).into_vec()]);
parent_header.set_seal(vec![encode(&4usize)]);
parent_header.set_gas_limit("222222".parse::<U256>().unwrap());
let mut header: Header = Header::default();
header.set_number(1);
@@ -1590,11 +1684,11 @@ mod tests {
let signature = tap.sign(addr, Some("0".into()), header.bare_hash()).unwrap();
// Two validators.
// Spec starts with step 2.
header.set_seal(vec![encode(&5usize).into_vec(), encode(&(&*signature as &[u8])).into_vec()]);
header.set_difficulty(calculate_score(U256::from(4), U256::from(5), U256::zero()));
header.set_seal(vec![encode(&5usize), encode(&(&*signature as &[u8]))]);
header.set_difficulty(calculate_score(4, 5, 0));
assert!(engine.verify_block_family(&header, &parent_header).is_ok());
header.set_seal(vec![encode(&3usize).into_vec(), encode(&(&*signature as &[u8])).into_vec()]);
header.set_difficulty(calculate_score(U256::from(4), U256::from(3), U256::zero()));
header.set_seal(vec![encode(&3usize), encode(&(&*signature as &[u8]))]);
header.set_difficulty(calculate_score(4, 3, 0));
assert!(engine.verify_block_family(&header, &parent_header).is_err());
}
@@ -1625,12 +1719,12 @@ mod tests {
};
let mut parent_header: Header = Header::default();
parent_header.set_seal(vec![encode(&1usize).into_vec()]);
parent_header.set_seal(vec![encode(&1usize)]);
parent_header.set_gas_limit("222222".parse::<U256>().unwrap());
let mut header: Header = Header::default();
header.set_difficulty(calculate_score(U256::from(1), U256::from(3), U256::zero()));
header.set_difficulty(calculate_score(1, 3, 0));
header.set_gas_limit("222222".parse::<U256>().unwrap());
header.set_seal(vec![encode(&3usize).into_vec()]);
header.set_seal(vec![encode(&3usize)]);
// Do not report when signer not present.
assert!(aura.verify_block_family(&header, &parent_header).is_ok());
@@ -1742,14 +1836,14 @@ mod tests {
(spec, tap, accounts)
}
fn empty_step(engine: &EthEngine, step: usize, parent_hash: &H256) -> EmptyStep {
fn empty_step(engine: &EthEngine, step: u64, parent_hash: &H256) -> EmptyStep {
let empty_step_rlp = super::empty_step_rlp(step, parent_hash);
let signature = engine.sign(keccak(&empty_step_rlp)).unwrap().into();
let parent_hash = parent_hash.clone();
EmptyStep { step, signature, parent_hash }
}
fn sealed_empty_step(engine: &EthEngine, step: usize, parent_hash: &H256) -> SealedEmptyStep {
fn sealed_empty_step(engine: &EthEngine, step: u64, parent_hash: &H256) -> SealedEmptyStep {
let empty_step_rlp = super::empty_step_rlp(step, parent_hash);
let signature = engine.sign(keccak(&empty_step_rlp)).unwrap().into();
SealedEmptyStep { signature, step }
@@ -1781,10 +1875,15 @@ mod tests {
assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None);
// spec starts with step 2
let empty_step_rlp = encode(&empty_step(engine, 2, &genesis_header.hash())).into_vec();
let empty_step_rlp = encode(&empty_step(engine, 2, &genesis_header.hash()));
// we've received the message
assert!(notify.messages.read().contains(&empty_step_rlp));
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!(len, notify.messages.read().len());
}
#[test]
@@ -1834,8 +1933,8 @@ mod tests {
let empty_step2 = sealed_empty_step(engine, 2, &genesis_header.hash());
let empty_steps = ::rlp::encode_list(&vec![empty_step2]);
assert_eq!(seal[0], encode(&3usize).into_vec());
assert_eq!(seal[2], empty_steps.into_vec());
assert_eq!(seal[0], encode(&3usize));
assert_eq!(seal[2], empty_steps);
}
}
@@ -1888,8 +1987,8 @@ mod tests {
let empty_steps = ::rlp::encode_list(&vec![empty_step2, empty_step3]);
assert_eq!(seal[0], encode(&4usize).into_vec());
assert_eq!(seal[2], empty_steps.into_vec());
assert_eq!(seal[0], encode(&4usize));
assert_eq!(seal[2], empty_steps);
}
}
@@ -1938,7 +2037,7 @@ mod tests {
let engine = &*spec.engine;
let mut parent_header: Header = Header::default();
parent_header.set_seal(vec![encode(&0usize).into_vec()]);
parent_header.set_seal(vec![encode(&0usize)]);
parent_header.set_gas_limit("222222".parse::<U256>().unwrap());
let mut header: Header = Header::default();
@@ -1952,9 +2051,9 @@ mod tests {
// empty step with invalid step
let empty_steps = vec![SealedEmptyStep { signature: 0.into(), step: 2 }];
header.set_seal(vec![
encode(&2usize).into_vec(),
encode(&(&*signature as &[u8])).into_vec(),
::rlp::encode_list(&empty_steps).into_vec(),
encode(&2usize),
encode(&(&*signature as &[u8])),
::rlp::encode_list(&empty_steps),
]);
assert!(match engine.verify_block_family(&header, &parent_header) {
@@ -1966,9 +2065,9 @@ mod tests {
// empty step with invalid signature
let empty_steps = vec![SealedEmptyStep { signature: 0.into(), step: 1 }];
header.set_seal(vec![
encode(&2usize).into_vec(),
encode(&(&*signature as &[u8])).into_vec(),
::rlp::encode_list(&empty_steps).into_vec(),
encode(&2usize),
encode(&(&*signature as &[u8])),
::rlp::encode_list(&empty_steps),
]);
assert!(match engine.verify_block_family(&header, &parent_header) {
@@ -1981,9 +2080,9 @@ mod tests {
engine.set_signer(tap.clone(), addr1, "1".into());
let empty_steps = vec![sealed_empty_step(engine, 1, &parent_header.hash())];
header.set_seal(vec![
encode(&2usize).into_vec(),
encode(&(&*signature as &[u8])).into_vec(),
::rlp::encode_list(&empty_steps).into_vec(),
encode(&2usize),
encode(&(&*signature as &[u8])),
::rlp::encode_list(&empty_steps),
]);
assert!(match engine.verify_block_family(&header, &parent_header) {
@@ -1999,12 +2098,12 @@ mod tests {
let empty_step3 = sealed_empty_step(engine, 3, &parent_header.hash());
let empty_steps = vec![empty_step2, empty_step3];
header.set_difficulty(calculate_score(U256::from(0), U256::from(4), U256::from(2)));
header.set_difficulty(calculate_score(0, 4, 2));
let signature = tap.sign(addr1, Some("1".into()), header.bare_hash()).unwrap();
header.set_seal(vec![
encode(&4usize).into_vec(),
encode(&(&*signature as &[u8])).into_vec(),
::rlp::encode_list(&empty_steps).into_vec(),
encode(&4usize),
encode(&(&*signature as &[u8])),
::rlp::encode_list(&empty_steps),
]);
assert!(engine.verify_block_family(&header, &parent_header).is_ok());
@@ -2093,9 +2192,9 @@ mod tests {
header.set_number(2);
header.set_seal(vec![
encode(&2usize).to_vec(),
encode(&H520::default()).to_vec(),
::rlp::encode_list(&vec![sealed_empty_step]).to_vec(),
encode(&2usize),
encode(&H520::default()),
::rlp::encode_list(&vec![sealed_empty_step]),
]);
let info = engine.extra_info(&header);
@@ -2114,4 +2213,52 @@ mod tests {
BTreeMap::default(),
);
}
#[test]
fn test_empty_steps() {
let last_benign = Arc::new(AtomicUsize::new(0));
let params = AuthorityRoundParams {
step_duration: 4,
start_step: Some(1),
validators: Box::new(TestSet::new(Default::default(), last_benign.clone())),
validate_score_transition: 0,
validate_step_transition: 0,
immediate_transitions: true,
maximum_uncle_count_transition: 0,
maximum_uncle_count: 0,
empty_steps_transition: 0,
maximum_empty_steps: 10,
block_reward: Default::default(),
block_reward_contract_transition: 0,
block_reward_contract: Default::default(),
};
let mut c_params = ::spec::CommonParams::default();
c_params.gas_limit_bound_divisor = 5.into();
let machine = ::machine::EthereumMachine::regular(c_params, Default::default());
let engine = AuthorityRound::new(params, machine).unwrap();
let parent_hash: H256 = 1.into();
let signature = H520::default();
let step = |step: u64| EmptyStep {
step,
parent_hash,
signature,
};
engine.handle_empty_step_message(step(1));
engine.handle_empty_step_message(step(3));
engine.handle_empty_step_message(step(2));
engine.handle_empty_step_message(step(1));
assert_eq!(engine.empty_steps(0, 4, parent_hash), vec![step(1), step(2), step(3)]);
assert_eq!(engine.empty_steps(2, 3, parent_hash), vec![]);
assert_eq!(engine.empty_steps(2, 4, parent_hash), vec![step(3)]);
engine.clear_empty_steps(2);
assert_eq!(engine.empty_steps(0, 3, parent_hash), vec![]);
assert_eq!(engine.empty_steps(0, 4, parent_hash), vec![step(3)]);
}
}

View File

@@ -110,7 +110,7 @@ impl Engine<EthereumMachine> for BasicAuthority {
if self.validators.contains(header.parent_hash(), author) {
// account should be pernamently unlocked, otherwise sealing will fail
if let Ok(signature) = self.sign(header.bare_hash()) {
return Seal::Regular(vec![::rlp::encode(&(&H520::from(signature) as &[u8])).into_vec()]);
return Seal::Regular(vec![::rlp::encode(&(&H520::from(signature) as &[u8]))]);
} else {
trace!(target: "basicauthority", "generate_seal: FAIL: accounts secret key unavailable");
}
@@ -150,6 +150,7 @@ impl Engine<EthereumMachine> for BasicAuthority {
fn is_epoch_end(
&self,
chain_head: &Header,
_finalized: &[H256],
_chain: &super::Headers<Header>,
_transition_store: &super::PendingTransitionStore,
) -> Option<Vec<u8>> {
@@ -159,6 +160,15 @@ impl Engine<EthereumMachine> for BasicAuthority {
self.validators.is_epoch_end(first, chain_head)
}
fn is_epoch_end_light(
&self,
chain_head: &Header,
chain: &super::Headers<Header>,
transition_store: &super::PendingTransitionStore,
) -> Option<Vec<u8>> {
self.is_epoch_end(chain_head, &[], chain, transition_store)
}
fn epoch_verifier<'a>(&self, header: &Header, proof: &'a [u8]) -> ConstructedVerifier<'a, EthereumMachine> {
let first = header.number() == 0;
@@ -234,7 +244,7 @@ mod tests {
fn can_do_signature_verification_fail() {
let engine = new_test_authority().engine;
let mut header: Header = Header::default();
header.set_seal(vec![::rlp::encode(&H520::default()).into_vec()]);
header.set_seal(vec![::rlp::encode(&H520::default())]);
let verify_result = engine.verify_block_external(&header);
assert!(verify_result.is_err());

View File

@@ -30,7 +30,7 @@ use trace;
use types::BlockNumber;
use super::{SystemOrCodeCall, SystemOrCodeCallKind};
use_contract!(block_reward_contract, "BlockReward", "res/contracts/block_reward.json");
use_contract!(block_reward_contract, "res/contracts/block_reward.json");
/// The kind of block reward.
/// Depending on the consensus engine the allocated block reward might have
@@ -81,7 +81,6 @@ impl Into<trace::RewardType> for RewardKind {
#[derive(PartialEq, Debug)]
pub struct BlockRewardContract {
kind: SystemOrCodeCallKind,
block_reward_contract: block_reward_contract::BlockReward,
}
impl BlockRewardContract {
@@ -89,7 +88,6 @@ impl BlockRewardContract {
pub fn new(kind: SystemOrCodeCallKind) -> BlockRewardContract {
BlockRewardContract {
kind,
block_reward_contract: block_reward_contract::BlockReward::default(),
}
}
@@ -114,9 +112,7 @@ impl BlockRewardContract {
beneficiaries: &[(Address, RewardKind)],
caller: &mut SystemOrCodeCall,
) -> Result<Vec<(Address, U256)>, Error> {
let reward = self.block_reward_contract.functions().reward();
let input = reward.input(
let input = block_reward_contract::functions::reward::encode_input(
beneficiaries.iter().map(|&(address, _)| H160::from(address)),
beneficiaries.iter().map(|&(_, ref reward_kind)| u16::from(*reward_kind)),
);

View File

@@ -120,7 +120,7 @@ mod tests {
assert!(engine.verify_block_basic(&header).is_ok());
header.set_seal(vec![::rlp::encode(&H520::default()).into_vec()]);
header.set_seal(vec![::rlp::encode(&H520::default())]);
assert!(engine.verify_block_unordered(&header).is_ok());
}

View File

@@ -254,6 +254,9 @@ pub trait Engine<M: Machine>: Sync + Send {
/// The number of generations back that uncles can be.
fn maximum_uncle_age(&self) -> usize { 6 }
/// Optional maximum gas limit.
fn maximum_gas_limit(&self) -> Option<U256> { None }
/// Block transformation functions, before the transactions.
/// `epoch_begin` set to true if this block kicks off an epoch.
fn on_new_block(
@@ -335,10 +338,30 @@ pub trait Engine<M: Machine>: Sync + Send {
///
/// This either means that an immediate transition occurs or a block signalling transition
/// has reached finality. The `Headers` given are not guaranteed to return any blocks
/// from any epoch other than the current.
/// from any epoch other than the current. The client must keep track of finality and provide
/// the latest finalized headers to check against the transition store.
///
/// Return optional transition proof.
fn is_epoch_end(
&self,
_chain_head: &M::Header,
_finalized: &[H256],
_chain: &Headers<M::Header>,
_transition_store: &PendingTransitionStore,
) -> Option<Vec<u8>> {
None
}
/// Whether a block is the end of an epoch.
///
/// This either means that an immediate transition occurs or a block signalling transition
/// has reached finality. The `Headers` given are not guaranteed to return any blocks
/// from any epoch other than the current. This is a specialized method to use for light
/// clients since the light client doesn't track finality of all blocks, and therefore finality
/// for blocks in the current epoch is built inside this method by the engine.
///
/// Return optional transition proof.
fn is_epoch_end_light(
&self,
_chain_head: &M::Header,
_chain: &Headers<M::Header>,
@@ -406,7 +429,7 @@ pub trait Engine<M: Machine>: Sync + Send {
/// Gather all ancestry actions. Called at the last stage when a block is committed. The Engine must guarantee that
/// the ancestry exists.
fn ancestry_actions(&self, _block: &M::LiveBlock, _ancestry: &mut Iterator<Item=M::ExtendedHeader>) -> Vec<AncestryAction> {
fn ancestry_actions(&self, _header: &M::Header, _ancestry: &mut Iterator<Item=M::ExtendedHeader>) -> Vec<AncestryAction> {
Vec::new()
}

View File

@@ -231,7 +231,7 @@ mod tests {
},
block_hash: Some(keccak("1")),
};
let raw_rlp = ::rlp::encode(&message).into_vec();
let raw_rlp = ::rlp::encode(&message);
let rlp = Rlp::new(&raw_rlp);
assert_eq!(Ok(message), rlp.as_val());
@@ -268,8 +268,8 @@ mod tests {
fn proposal_message() {
let mut header = Header::default();
let seal = vec![
::rlp::encode(&0u8).into_vec(),
::rlp::encode(&H520::default()).into_vec(),
::rlp::encode(&0u8),
::rlp::encode(&H520::default()),
Vec::new()
];

View File

@@ -407,9 +407,9 @@ impl Tendermint {
let precommits = self.votes.round_signatures(vote_step, &bh);
trace!(target: "engine", "Collected seal: {:?}", precommits);
let seal = vec![
::rlp::encode(&vote_step.view).into_vec(),
::rlp::encode(&vote_step.view),
::rlp::NULL_RLP.to_vec(),
::rlp::encode_list(&precommits).into_vec()
::rlp::encode_list(&precommits)
];
self.submit_seal(bh, seal);
self.votes.throw_out_old(&vote_step);
@@ -491,8 +491,8 @@ impl Engine<EthereumMachine> for Tendermint {
*self.proposal.write() = bh;
*self.proposal_parent.write() = header.parent_hash().clone();
Seal::Proposal(vec![
::rlp::encode(&view).into_vec(),
::rlp::encode(&signature).into_vec(),
::rlp::encode(&view),
::rlp::encode(&signature),
::rlp::EMPTY_LIST_RLP.to_vec()
])
} else {
@@ -520,7 +520,7 @@ impl Engine<EthereumMachine> for Tendermint {
self.broadcast_message(rlp.as_raw().to_vec());
if let Some(double) = self.votes.vote(message.clone(), sender) {
let height = message.vote_step.height as BlockNumber;
self.validators.report_malicious(&sender, height, height, ::rlp::encode(&double).into_vec());
self.validators.report_malicious(&sender, height, height, ::rlp::encode(&double));
return Err(EngineError::DoubleVote(sender));
}
trace!(target: "engine", "Handling a valid {:?} from {}.", message, sender);
@@ -635,6 +635,7 @@ impl Engine<EthereumMachine> for Tendermint {
fn is_epoch_end(
&self,
chain_head: &Header,
_finalized: &[H256],
_chain: &super::Headers<Header>,
transition_store: &super::PendingTransitionStore,
) -> Option<Vec<u8>> {
@@ -652,6 +653,15 @@ impl Engine<EthereumMachine> for Tendermint {
None
}
fn is_epoch_end_light(
&self,
chain_head: &Header,
chain: &super::Headers<Header>,
transition_store: &super::PendingTransitionStore,
) -> Option<Vec<u8>> {
self.is_epoch_end(chain_head, &[], chain, transition_store)
}
fn epoch_verifier<'a>(&self, _header: &Header, proof: &'a [u8]) -> ConstructedVerifier<'a, EthereumMachine> {
let (signal_number, set_proof, finality_proof) = match destructure_proofs(proof) {
Ok(x) => x,
@@ -823,8 +833,8 @@ mod tests {
let vote_info = message_info_rlp(&VoteStep::new(header.number() as Height, view, Step::Propose), Some(header.bare_hash()));
let signature = tap.sign(*author, None, keccak(vote_info)).unwrap();
vec![
::rlp::encode(&view).into_vec(),
::rlp::encode(&H520::from(signature)).into_vec(),
::rlp::encode(&view),
::rlp::encode(&H520::from(signature)),
::rlp::EMPTY_LIST_RLP.to_vec()
]
}
@@ -928,7 +938,7 @@ mod tests {
let signature1 = tap.sign(proposer, None, keccak(&vote_info)).unwrap();
seal[1] = ::rlp::NULL_RLP.to_vec();
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone())]).into_vec();
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone())]);
header.set_seal(seal.clone());
// One good signature is not enough.
@@ -940,7 +950,7 @@ mod tests {
let voter = insert_and_unlock(&tap, "0");
let signature0 = tap.sign(voter, None, keccak(&vote_info)).unwrap();
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone()), H520::from(signature0.clone())]).into_vec();
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone()), H520::from(signature0.clone())]);
header.set_seal(seal.clone());
assert!(engine.verify_block_external(&header).is_ok());
@@ -948,7 +958,7 @@ mod tests {
let bad_voter = insert_and_unlock(&tap, "101");
let bad_signature = tap.sign(bad_voter, None, keccak(vote_info)).unwrap();
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1), H520::from(bad_signature)]).into_vec();
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1), H520::from(bad_signature)]);
header.set_seal(seal);
// One good and one bad signature.
@@ -1084,7 +1094,7 @@ mod tests {
let signature0 = tap.sign(voter, None, keccak(&vote_info)).unwrap();
seal[1] = ::rlp::NULL_RLP.to_vec();
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone())]).into_vec();
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone())]);
header.set_seal(seal.clone());
let epoch_verifier = super::EpochVerifier {
@@ -1112,7 +1122,7 @@ mod tests {
_ => panic!(),
}
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone()), H520::from(signature0.clone())]).into_vec();
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone()), H520::from(signature0.clone())]);
header.set_seal(seal.clone());
assert!(epoch_verifier.verify_light(&header).is_ok());
@@ -1120,7 +1130,7 @@ mod tests {
let bad_voter = insert_and_unlock(&tap, "101");
let bad_signature = tap.sign(bad_voter, None, keccak(&vote_info)).unwrap();
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1), H520::from(bad_signature)]).into_vec();
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1), H520::from(bad_signature)]);
header.set_seal(seal);
// One good and one bad signature.

View File

@@ -30,13 +30,12 @@ use machine::{AuxiliaryData, Call, EthereumMachine};
use super::{ValidatorSet, SimpleList, SystemCall};
use super::safe_contract::ValidatorSafeContract;
use_contract!(validator_report, "ValidatorReport", "res/contracts/validator_report.json");
use_contract!(validator_report, "res/contracts/validator_report.json");
/// A validator contract with reporting.
pub struct ValidatorContract {
contract_address: Address,
validators: ValidatorSafeContract,
provider: validator_report::ValidatorReport,
client: RwLock<Option<Weak<EngineClient>>>, // TODO [keorn]: remove
}
@@ -45,7 +44,6 @@ impl ValidatorContract {
ValidatorContract {
contract_address,
validators: ValidatorSafeContract::new(contract_address),
provider: validator_report::ValidatorReport::default(),
client: RwLock::new(None),
}
}
@@ -111,7 +109,7 @@ impl ValidatorSet for ValidatorContract {
}
fn report_malicious(&self, address: &Address, _set_block: BlockNumber, block: BlockNumber, proof: Bytes) {
let data = self.provider.functions().report_malicious().input(*address, block, proof);
let data = validator_report::functions::report_malicious::encode_input(*address, block, proof);
match self.transact(data) {
Ok(_) => warn!(target: "engine", "Reported malicious validator {}", address),
Err(s) => warn!(target: "engine", "Validator {} could not be reported {}", address, s),
@@ -119,7 +117,7 @@ impl ValidatorSet for ValidatorContract {
}
fn report_benign(&self, address: &Address, _set_block: BlockNumber, block: BlockNumber) {
let data = self.provider.functions().report_benign().input(*address, block);
let data = validator_report::functions::report_benign::encode_input(*address, block);
match self.transact(data) {
Ok(_) => warn!(target: "engine", "Reported benign validator misbehaviour {}", address),
Err(s) => warn!(target: "engine", "Validator {} could not be reported {}", address, s),
@@ -174,7 +172,7 @@ mod tests {
// Check a block that is a bit in future, reject it but don't report the validator.
let mut header = Header::default();
let seal = vec![encode(&4u8).into_vec(), encode(&(&H520::default() as &[u8])).into_vec()];
let seal = vec![encode(&4u8), encode(&(&H520::default() as &[u8]))];
header.set_seal(seal);
header.set_author(v1);
header.set_number(2);
@@ -185,7 +183,7 @@ mod tests {
// Now create one that is more in future. That one should be rejected and validator should be reported.
let mut header = Header::default();
let seal = vec![encode(&8u8).into_vec(), encode(&(&H520::default() as &[u8])).into_vec()];
let seal = vec![encode(&8u8), encode(&(&H520::default() as &[u8]))];
header.set_seal(seal);
header.set_author(v1);
header.set_number(2);

View File

@@ -33,8 +33,9 @@ use std::sync::{Weak, Arc};
use super::{SystemCall, ValidatorSet};
use super::simple_list::SimpleList;
use unexpected::Mismatch;
use ethabi::FunctionOutputDecoder;
use_contract!(validator_set, "ValidatorSet", "res/contracts/validator_set.json");
use_contract!(validator_set, "res/contracts/validator_set.json");
const MEMOIZE_CAPACITY: usize = 500;
@@ -50,12 +51,11 @@ lazy_static! {
struct StateProof {
contract_address: Address,
header: Header,
provider: validator_set::ValidatorSet,
}
impl ::engines::StateDependentProof<EthereumMachine> for StateProof {
fn generate_proof(&self, caller: &Call) -> Result<Vec<u8>, String> {
prove_initial(&self.provider, self.contract_address, &self.header, caller)
prove_initial(self.contract_address, &self.header, caller)
}
fn check_proof(&self, machine: &EthereumMachine, proof: &[u8]) -> Result<(), String> {
@@ -65,7 +65,7 @@ impl ::engines::StateDependentProof<EthereumMachine> for StateProof {
return Err("wrong header in proof".into());
}
check_first_proof(machine, &self.provider, self.contract_address, header, &state_items).map(|_| ())
check_first_proof(machine, self.contract_address, header, &state_items).map(|_| ())
}
}
@@ -73,7 +73,6 @@ impl ::engines::StateDependentProof<EthereumMachine> for StateProof {
pub struct ValidatorSafeContract {
contract_address: Address,
validators: RwLock<MemoryLruCache<H256, SimpleList>>,
provider: validator_set::ValidatorSet,
client: RwLock<Option<Weak<EngineClient>>>, // TODO [keorn]: remove
}
@@ -89,7 +88,7 @@ fn encode_first_proof(header: &Header, state_items: &[Vec<u8>]) -> Bytes {
}
// check a first proof: fetch the validator set at the given block.
fn check_first_proof(machine: &EthereumMachine, provider: &validator_set::ValidatorSet, contract_address: Address, old_header: Header, state_items: &[DBValue])
fn check_first_proof(machine: &EthereumMachine, contract_address: Address, old_header: Header, state_items: &[DBValue])
-> Result<Vec<Address>, String>
{
use transaction::{Action, Transaction};
@@ -114,31 +113,31 @@ fn check_first_proof(machine: &EthereumMachine, provider: &validator_set::Valida
// check state proof using given machine.
let number = old_header.number();
provider.functions().get_validators().call(&|data| {
let from = Address::default();
let tx = Transaction {
nonce: machine.account_start_nonce(number),
action: Action::Call(contract_address),
gas: PROVIDED_GAS.into(),
gas_price: U256::default(),
value: U256::default(),
data,
}.fake_sign(from);
let (data, decoder) = validator_set::functions::get_validators::call();
let res = ::state::check_proof(
state_items,
*old_header.state_root(),
&tx,
machine,
&env_info,
);
let from = Address::default();
let tx = Transaction {
nonce: machine.account_start_nonce(number),
action: Action::Call(contract_address),
gas: PROVIDED_GAS.into(),
gas_price: U256::default(),
value: U256::default(),
data,
}.fake_sign(from);
match res {
::state::ProvedExecution::BadProof => Err("Bad proof".into()),
::state::ProvedExecution::Failed(e) => Err(format!("Failed call: {}", e)),
::state::ProvedExecution::Complete(e) => Ok(e.output),
}
}).map_err(|err| err.to_string())
let res = ::state::check_proof(
state_items,
*old_header.state_root(),
&tx,
machine,
&env_info,
);
match res {
::state::ProvedExecution::BadProof => Err("Bad proof".into()),
::state::ProvedExecution::Failed(e) => Err(format!("Failed call: {}", e)),
::state::ProvedExecution::Complete(e) => decoder.decode(&e.output).map_err(|e| e.to_string()),
}
}
fn decode_first_proof(rlp: &Rlp) -> Result<(Header, Vec<DBValue>), ::error::Error> {
@@ -158,7 +157,7 @@ fn decode_first_proof(rlp: &Rlp) -> Result<(Header, Vec<DBValue>), ::error::Erro
fn encode_proof(header: &Header, receipts: &[Receipt]) -> Bytes {
let mut stream = RlpStream::new_list(2);
stream.append(header).append_list(receipts);
stream.drain().into_vec()
stream.drain()
}
fn decode_proof(rlp: &Rlp) -> Result<(Header, Vec<Receipt>), ::error::Error> {
@@ -167,32 +166,26 @@ fn decode_proof(rlp: &Rlp) -> Result<(Header, Vec<Receipt>), ::error::Error> {
// given a provider and caller, generate proof. this will just be a state proof
// of `getValidators`.
fn prove_initial(provider: &validator_set::ValidatorSet, contract_address: Address, header: &Header, caller: &Call) -> Result<Vec<u8>, String> {
fn prove_initial(contract_address: Address, header: &Header, caller: &Call) -> Result<Vec<u8>, String> {
use std::cell::RefCell;
let epoch_proof = RefCell::new(None);
let res = {
let caller = |data| {
let (result, proof) = caller(contract_address, data)?;
*epoch_proof.borrow_mut() = Some(encode_first_proof(header, &proof));
Ok(result)
};
provider.functions().get_validators().call(&caller)
.map_err(|err| err.to_string())
let validators = {
let (data, decoder) = validator_set::functions::get_validators::call();
let (value, proof) = caller(contract_address, data)?;
*epoch_proof.borrow_mut() = Some(encode_first_proof(header, &proof));
decoder.decode(&value).map_err(|e| e.to_string())?
};
res.map(|validators| {
let proof = epoch_proof.into_inner().expect("epoch_proof always set after call; qed");
let proof = epoch_proof.into_inner().expect("epoch_proof always set after call; qed");
trace!(target: "engine", "obtained proof for initial set: {} validators, {} bytes",
validators.len(), proof.len());
trace!(target: "engine", "obtained proof for initial set: {} validators, {} bytes",
validators.len(), proof.len());
info!(target: "engine", "Signal for switch to contract-based validator set.");
info!(target: "engine", "Initial contract validators: {:?}", validators);
info!(target: "engine", "Signal for switch to contract-based validator set.");
info!(target: "engine", "Initial contract validators: {:?}", validators);
proof
})
Ok(proof)
}
impl ValidatorSafeContract {
@@ -200,7 +193,6 @@ impl ValidatorSafeContract {
ValidatorSafeContract {
contract_address,
validators: RwLock::new(MemoryLruCache::new(MEMOIZE_CAPACITY)),
provider: validator_set::ValidatorSet::default(),
client: RwLock::new(None),
}
}
@@ -208,8 +200,11 @@ impl ValidatorSafeContract {
/// Queries the state and gets the set of validators.
fn get_list(&self, caller: &Call) -> Option<SimpleList> {
let contract_address = self.contract_address;
let caller = move |data| caller(contract_address, data).map(|x| x.0);
match self.provider.functions().get_validators().call(&caller) {
let (data, decoder) = validator_set::functions::get_validators::call();
let value = caller(contract_address, data).and_then(|x| decoder.decode(&x.0).map_err(|e| e.to_string()));
match value {
Ok(new) => {
debug!(target: "engine", "Set of validators obtained: {:?}", new);
Some(SimpleList::new(new))
@@ -259,7 +254,6 @@ impl ValidatorSafeContract {
log.topics[1] == *header.parent_hash()
};
let event = self.provider.events().initiate_change();
//// iterate in reverse because only the _last_ change in a given
//// block actually has any effect.
//// the contract should only increment the nonce once.
@@ -269,7 +263,7 @@ impl ValidatorSafeContract {
.flat_map(|r| r.logs.iter())
.filter(move |l| check_log(l))
.filter_map(|log| {
event.parse_log((log.topics.clone(), log.data.clone()).into()).ok()
validator_set::events::initiate_change::parse_log((log.topics.clone(), log.data.clone()).into()).ok()
});
// only last log is taken into account
@@ -296,7 +290,7 @@ impl ValidatorSet for ValidatorSafeContract {
}
fn on_epoch_begin(&self, _first: bool, _header: &Header, caller: &mut SystemCall) -> Result<(), ::error::Error> {
let data = self.provider.functions().finalize_change().input();
let data = validator_set::functions::finalize_change::encode_input();
caller(self.contract_address, data)
.map(|_| ())
.map_err(::engines::EngineError::FailedSystemCall)
@@ -304,7 +298,7 @@ impl ValidatorSet for ValidatorSafeContract {
}
fn genesis_epoch_data(&self, header: &Header, call: &Call) -> Result<Vec<u8>, String> {
prove_initial(&self.provider, self.contract_address, header, call)
prove_initial(self.contract_address, header, call)
}
fn is_epoch_end(&self, _first: bool, _chain_head: &Header) -> Option<Vec<u8>> {
@@ -322,7 +316,6 @@ impl ValidatorSet for ValidatorSafeContract {
let state_proof = Arc::new(StateProof {
contract_address: self.contract_address,
header: header.clone(),
provider: validator_set::ValidatorSet::default(),
});
return ::engines::EpochChange::Yes(::engines::Proof::WithState(state_proof as Arc<_>));
}
@@ -361,7 +354,7 @@ impl ValidatorSet for ValidatorSafeContract {
let (old_header, state_items) = decode_first_proof(&rlp)?;
let number = old_header.number();
let old_hash = old_header.hash();
let addresses = check_first_proof(machine, &self.provider, self.contract_address, old_header, &state_items)
let addresses = check_first_proof(machine, self.contract_address, old_header, &state_items)
.map_err(::engines::EngineError::InsufficientProof)?;
trace!(target: "engine", "extracted epoch set at #{}: {} addresses",

View File

@@ -29,6 +29,7 @@ use engines::EngineError;
use ethkey::Error as EthkeyError;
use account_provider::SignError as AccountsError;
use transaction::Error as TransactionError;
use rlp;
pub use executed::{ExecutionError, CallError};
@@ -194,40 +195,6 @@ error_chain! {
}
}
error_chain! {
types {
BlockImportError, BlockImportErrorKind, BlockImportErrorResultExt;
}
links {
Import(ImportError, ImportErrorKind) #[doc = "Import error"];
Queue(QueueError, QueueErrorKind) #[doc = "Io channel queue error"];
}
foreign_links {
Block(BlockError) #[doc = "Block error"];
Decoder(::rlp::DecoderError) #[doc = "Rlp decoding error"];
}
errors {
#[doc = "Other error"]
Other(err: String) {
description("Other error")
display("Other error {}", err)
}
}
}
impl From<Error> for BlockImportError {
fn from(e: Error) -> Self {
match e {
Error(ErrorKind::Block(block_error), _) => BlockImportErrorKind::Block(block_error).into(),
Error(ErrorKind::Import(import_error), _) => BlockImportErrorKind::Import(import_error.into()).into(),
_ => BlockImportErrorKind::Other(format!("other block import error: {:?}", e)).into(),
}
}
}
/// Api-level error for transaction import
#[derive(Debug, Clone)]
pub enum TransactionImportError {
@@ -253,6 +220,7 @@ error_chain! {
links {
Import(ImportError, ImportErrorKind) #[doc = "Error concerning block import." ];
Queue(QueueError, QueueErrorKind) #[doc = "Io channel queue error"];
}
foreign_links {
@@ -265,6 +233,7 @@ error_chain! {
Snappy(InvalidInput) #[doc = "Snappy error."];
Engine(EngineError) #[doc = "Consensus vote error."];
Ethkey(EthkeyError) #[doc = "Ethkey error."];
Decoder(rlp::DecoderError) #[doc = "RLP decoding errors"];
}
errors {
@@ -297,40 +266,15 @@ error_chain! {
description("Unknown engine name")
display("Unknown engine name ({})", name)
}
#[doc = "RLP decoding errors"]
Decoder(err: ::rlp::DecoderError) {
description("decoding value failed")
display("decoding value failed with error: {}", err)
}
}
}
/// Result of import block operation.
pub type ImportResult = EthcoreResult<H256>;
impl From<AccountsError> for Error {
fn from(err: AccountsError) -> Error {
ErrorKind::AccountProvider(err).into()
}
}
impl From<::rlp::DecoderError> for Error {
fn from(err: ::rlp::DecoderError) -> Error {
ErrorKind::Decoder(err).into()
}
}
impl From<BlockImportError> for Error {
fn from(err: BlockImportError) -> Error {
match err {
BlockImportError(BlockImportErrorKind::Block(e), _) => ErrorKind::Block(e).into(),
BlockImportError(BlockImportErrorKind::Import(e), _) => ErrorKind::Import(e).into(),
_ => ErrorKind::Msg(format!("other block import error: {:?}", err)).into(),
}
}
}
impl From<SnapshotError> for Error {
fn from(err: SnapshotError) -> Error {
match err {

View File

@@ -21,7 +21,7 @@ use std::sync::Arc;
use hash::{KECCAK_EMPTY_LIST_RLP};
use engines::block_reward::{self, BlockRewardContract, RewardKind};
use ethash::{self, quick_get_difficulty, slow_hash_block_number, EthashManager, OptimizeFor};
use ethereum_types::{H256, H64, U256, Address};
use ethereum_types::{H256, H64, U256};
use unexpected::{OutOfBounds, Mismatch};
use block::*;
use error::{BlockError, Error};
@@ -98,18 +98,6 @@ pub struct EthashParams {
pub ecip1010_continue_transition: u64,
/// Total block number for one ECIP-1017 era.
pub ecip1017_era_rounds: u64,
/// Number of first block where MCIP-3 begins.
pub mcip3_transition: u64,
/// MCIP-3 Block reward coin-base for miners.
pub mcip3_miner_reward: U256,
/// MCIP-3 Block reward ubi-base for basic income.
pub mcip3_ubi_reward: U256,
/// MCIP-3 contract address for universal basic income.
pub mcip3_ubi_contract: Address,
/// MCIP-3 Block reward dev-base for dev funds.
pub mcip3_dev_reward: U256,
/// MCIP-3 contract address for the developer funds.
pub mcip3_dev_contract: Address,
/// Block reward in base units.
pub block_reward: BTreeMap<BlockNumber, U256>,
/// EXPIP-2 block height
@@ -140,12 +128,6 @@ impl From<ethjson::spec::EthashParams> for EthashParams {
ecip1010_pause_transition: p.ecip1010_pause_transition.map_or(u64::max_value(), Into::into),
ecip1010_continue_transition: p.ecip1010_continue_transition.map_or(u64::max_value(), Into::into),
ecip1017_era_rounds: p.ecip1017_era_rounds.map_or(u64::max_value(), Into::into),
mcip3_transition: p.mcip3_transition.map_or(u64::max_value(), Into::into),
mcip3_miner_reward: p.mcip3_miner_reward.map_or_else(Default::default, Into::into),
mcip3_ubi_reward: p.mcip3_ubi_reward.map_or(U256::from(0), Into::into),
mcip3_ubi_contract: p.mcip3_ubi_contract.map_or_else(Address::new, Into::into),
mcip3_dev_reward: p.mcip3_dev_reward.map_or(U256::from(0), Into::into),
mcip3_dev_contract: p.mcip3_dev_contract.map_or_else(Address::new, Into::into),
block_reward: p.block_reward.map_or_else(
|| {
let mut ret = BTreeMap::new();
@@ -240,6 +222,8 @@ impl Engine<EthereumMachine> for Arc<Ethash> {
fn maximum_uncle_count(&self, _block: BlockNumber) -> usize { 2 }
fn maximum_gas_limit(&self) -> Option<U256> { Some(0x7fff_ffff_ffff_ffffu64.into()) }
fn populate_from_parent(&self, header: &mut Header, parent: &Header) {
let difficulty = self.calculate_difficulty(header, parent);
header.set_difficulty(difficulty);
@@ -287,21 +271,7 @@ impl Engine<EthereumMachine> for Arc<Ethash> {
// Bestow block rewards.
let mut result_block_reward = reward + reward.shr(5) * U256::from(n_uncles);
if number >= self.ethash_params.mcip3_transition {
result_block_reward = self.ethash_params.mcip3_miner_reward;
let ubi_contract = self.ethash_params.mcip3_ubi_contract;
let ubi_reward = self.ethash_params.mcip3_ubi_reward;
let dev_contract = self.ethash_params.mcip3_dev_contract;
let dev_reward = self.ethash_params.mcip3_dev_reward;
rewards.push((author, RewardKind::Author, result_block_reward));
rewards.push((ubi_contract, RewardKind::External, ubi_reward));
rewards.push((dev_contract, RewardKind::External, dev_reward));
} else {
rewards.push((author, RewardKind::Author, result_block_reward));
}
rewards.push((author, RewardKind::Author, result_block_reward));
// Bestow uncle rewards.
for u in LiveBlock::uncles(&*block) {
@@ -354,10 +324,6 @@ impl Engine<EthereumMachine> for Arc<Ethash> {
return Err(From::from(BlockError::InvalidProofOfWork(OutOfBounds { min: Some(header.difficulty().clone()), max: None, found: difficulty })));
}
if header.gas_limit() > &0x7fffffffffffffffu64.into() {
return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds { min: None, max: Some(0x7fffffffffffffffu64.into()), found: header.gas_limit().clone() })));
}
Ok(())
}
@@ -549,12 +515,6 @@ mod tests {
ecip1010_pause_transition: u64::max_value(),
ecip1010_continue_transition: u64::max_value(),
ecip1017_era_rounds: u64::max_value(),
mcip3_transition: u64::max_value(),
mcip3_miner_reward: 0.into(),
mcip3_ubi_reward: 0.into(),
mcip3_ubi_contract: "0000000000000000000000000000000000000001".into(),
mcip3_dev_reward: 0.into(),
mcip3_dev_contract: "0000000000000000000000000000000000000001".into(),
expip2_transition: u64::max_value(),
expip2_duration_limit: 30,
block_reward_contract: None,
@@ -681,7 +641,7 @@ mod tests {
fn can_do_difficulty_verification_fail() {
let engine = test_spec().engine;
let mut header: Header = Header::default();
header.set_seal(vec![rlp::encode(&H256::zero()).into_vec(), rlp::encode(&H64::zero()).into_vec()]);
header.set_seal(vec![rlp::encode(&H256::zero()), rlp::encode(&H64::zero())]);
let verify_result = engine.verify_block_basic(&header);
@@ -696,7 +656,7 @@ mod tests {
fn can_do_proof_of_work_verification_fail() {
let engine = test_spec().engine;
let mut header: Header = Header::default();
header.set_seal(vec![rlp::encode(&H256::zero()).into_vec(), rlp::encode(&H64::zero()).into_vec()]);
header.set_seal(vec![rlp::encode(&H256::zero()), rlp::encode(&H64::zero())]);
header.set_difficulty(U256::from_str("ffffffffffffffffffffffffffffffffffffffffffffaaaaaaaaaaaaaaaaaaaa").unwrap());
let verify_result = engine.verify_block_basic(&header);
@@ -737,7 +697,7 @@ mod tests {
fn can_do_seal256_verification_fail() {
let engine = test_spec().engine;
let mut header: Header = Header::default();
header.set_seal(vec![rlp::encode(&H256::zero()).into_vec(), rlp::encode(&H64::zero()).into_vec()]);
header.set_seal(vec![rlp::encode(&H256::zero()), rlp::encode(&H64::zero())]);
let verify_result = engine.verify_block_unordered(&header);
match verify_result {
@@ -751,7 +711,7 @@ mod tests {
fn can_do_proof_of_work_unordered_verification_fail() {
let engine = test_spec().engine;
let mut header: Header = Header::default();
header.set_seal(vec![rlp::encode(&H256::from("b251bd2e0283d0658f2cadfdc8ca619b5de94eca5742725e2e757dd13ed7503d")).into_vec(), rlp::encode(&H64::zero()).into_vec()]);
header.set_seal(vec![rlp::encode(&H256::from("b251bd2e0283d0658f2cadfdc8ca619b5de94eca5742725e2e757dd13ed7503d")), rlp::encode(&H64::zero())]);
header.set_difficulty(U256::from_str("ffffffffffffffffffffffffffffffffffffffffffffaaaaaaaaaaaaaaaaaaaa").unwrap());
let verify_result = engine.verify_block_unordered(&header);
@@ -944,7 +904,7 @@ mod tests {
let tempdir = TempDir::new("").unwrap();
let ethash = Ethash::new(tempdir.path(), ethparams, machine, None);
let mut header = Header::default();
header.set_seal(vec![rlp::encode(&H256::from("b251bd2e0283d0658f2cadfdc8ca619b5de94eca5742725e2e757dd13ed7503d")).into_vec(), rlp::encode(&H64::zero()).into_vec()]);
header.set_seal(vec![rlp::encode(&H256::from("b251bd2e0283d0658f2cadfdc8ca619b5de94eca5742725e2e757dd13ed7503d")), rlp::encode(&H64::zero())]);
let info = ethash.extra_info(&header);
assert_eq!(info["nonce"], "0x0000000000000000");
assert_eq!(info["mixHash"], "0xb251bd2e0283d0658f2cadfdc8ca619b5de94eca5742725e2e757dd13ed7503d");

View File

@@ -69,6 +69,8 @@ pub fn new_expanse<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
/// Create a new Musicoin mainnet chain spec.
pub fn new_musicoin<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
// The musicoin chain spec uses a block reward contract which can be found at
// https://gist.github.com/andresilva/6f2afaf9486732a0797f4bdeae018ee9
load(params.into(), include_bytes!("../../res/ethereum/musicoin.json"))
}
@@ -87,11 +89,6 @@ pub fn new_social<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/social.json"))
}
/// Create a new Olympic testnet chain spec.
pub fn new_olympic<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/olympic.json"))
}
/// Create a new Morden testnet chain spec.
pub fn new_morden<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/morden.json"))
@@ -112,6 +109,11 @@ pub fn new_sokol<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/poasokol.json"))
}
/// Create a new Callisto chaun spec
pub fn new_callisto<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/callisto.json"))
}
// For tests
/// Create a new Foundation Frontier-era chain spec as though it never changes to Homestead.

File diff suppressed because it is too large Load Diff

View File

@@ -25,9 +25,8 @@ use executive::*;
use vm::{
self, ActionParams, ActionValue, EnvInfo, CallType, Schedule,
Ext, ContractCreateResult, MessageCallResult, CreateContractAddress,
ReturnData
ReturnData, TrapKind
};
use evm::FinalizationResult;
use transaction::UNSIGNED_SENDER;
use trace::{Tracer, VMTracer};
@@ -67,7 +66,8 @@ pub struct Externalities<'a, T: 'a, V: 'a, B: 'a> {
state: &'a mut State<B>,
env_info: &'a EnvInfo,
depth: usize,
origin_info: OriginInfo,
stack_depth: usize,
origin_info: &'a OriginInfo,
substate: &'a mut Substate,
machine: &'a Machine,
schedule: &'a Schedule,
@@ -87,7 +87,8 @@ impl<'a, T: 'a, V: 'a, B: 'a> Externalities<'a, T, V, B>
machine: &'a Machine,
schedule: &'a Schedule,
depth: usize,
origin_info: OriginInfo,
stack_depth: usize,
origin_info: &'a OriginInfo,
substate: &'a mut Substate,
output: OutputPolicy,
tracer: &'a mut T,
@@ -98,6 +99,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Externalities<'a, T, V, B>
state: state,
env_info: env_info,
depth: depth,
stack_depth: stack_depth,
origin_info: origin_info,
substate: substate,
machine: machine,
@@ -176,7 +178,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
};
let mut ex = Executive::new(self.state, self.env_info, self.machine, self.schedule);
let r = ex.call(params, self.substate, self.tracer, self.vm_tracer);
let r = ex.call_with_crossbeam(params, self.substate, self.stack_depth + 1, self.tracer, self.vm_tracer);
let output = match &r {
Ok(ref r) => H256::from(&r.return_data[..32]),
_ => H256::new(),
@@ -206,14 +208,15 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
gas: &U256,
value: &U256,
code: &[u8],
address_scheme: CreateContractAddress
) -> ContractCreateResult {
address_scheme: CreateContractAddress,
trap: bool,
) -> ::std::result::Result<ContractCreateResult, TrapKind> {
// create new contract address
let (address, code_hash) = match self.state.nonce(&self.origin_info.address) {
Ok(nonce) => contract_address(address_scheme, &self.origin_info.address, &nonce, &code),
Err(e) => {
debug!(target: "ext", "Database corruption encountered: {:?}", e);
return ContractCreateResult::Failed
return Ok(ContractCreateResult::Failed)
}
};
@@ -237,23 +240,19 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
if !self.schedule.keep_unsigned_nonce || params.sender != UNSIGNED_SENDER {
if let Err(e) = self.state.inc_nonce(&self.origin_info.address) {
debug!(target: "ext", "Database corruption encountered: {:?}", e);
return ContractCreateResult::Failed
return Ok(ContractCreateResult::Failed)
}
}
}
let mut ex = Executive::from_parent(self.state, self.env_info, self.machine, self.schedule, self.depth, self.static_flag);
if trap {
return Err(TrapKind::Create(params, address));
}
// TODO: handle internal error separately
match ex.create(params, self.substate, self.tracer, self.vm_tracer) {
Ok(FinalizationResult{ gas_left, apply_state: true, .. }) => {
self.substate.contracts_created.push(address.clone());
ContractCreateResult::Created(address, gas_left)
},
Ok(FinalizationResult{ gas_left, apply_state: false, return_data }) => {
ContractCreateResult::Reverted(gas_left, return_data)
},
_ => ContractCreateResult::Failed,
}
let mut ex = Executive::from_parent(self.state, self.env_info, self.machine, self.schedule, self.depth, self.static_flag);
let out = ex.create_with_crossbeam(params, self.substate, self.stack_depth + 1, self.tracer, self.vm_tracer);
Ok(into_contract_create_result(out, &address, self.substate))
}
fn call(
@@ -264,8 +263,9 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
value: Option<U256>,
data: &[u8],
code_address: &Address,
call_type: CallType
) -> MessageCallResult {
call_type: CallType,
trap: bool,
) -> ::std::result::Result<MessageCallResult, TrapKind> {
trace!(target: "externalities", "call");
let code_res = self.state.code(code_address)
@@ -273,7 +273,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
let (code, code_hash) = match code_res {
Ok((code, hash)) => (code, hash),
Err(_) => return MessageCallResult::Failed,
Err(_) => return Ok(MessageCallResult::Failed),
};
let mut params = ActionParams {
@@ -295,13 +295,13 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
params.value = ActionValue::Transfer(value);
}
let mut ex = Executive::from_parent(self.state, self.env_info, self.machine, self.schedule, self.depth, self.static_flag);
match ex.call(params, self.substate, self.tracer, self.vm_tracer) {
Ok(FinalizationResult{ gas_left, return_data, apply_state: true }) => MessageCallResult::Success(gas_left, return_data),
Ok(FinalizationResult{ gas_left, return_data, apply_state: false }) => MessageCallResult::Reverted(gas_left, return_data),
_ => MessageCallResult::Failed
if trap {
return Err(TrapKind::Call(params));
}
let mut ex = Executive::from_parent(self.state, self.env_info, self.machine, self.schedule, self.depth, self.static_flag);
let out = ex.call_with_crossbeam(params, self.substate, self.stack_depth + 1, self.tracer, self.vm_tracer);
Ok(into_message_call_result(out))
}
fn extcode(&self, address: &Address) -> vm::Result<Option<Arc<Bytes>>> {
@@ -406,12 +406,12 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
self.vm_tracer.trace_next_instruction(pc, instruction, current_gas)
}
fn trace_prepare_execute(&mut self, pc: usize, instruction: u8, gas_cost: U256) {
self.vm_tracer.trace_prepare_execute(pc, instruction, gas_cost)
fn trace_prepare_execute(&mut self, pc: usize, instruction: u8, gas_cost: U256, mem_written: Option<(usize, usize)>, store_written: Option<(U256, U256)>) {
self.vm_tracer.trace_prepare_execute(pc, instruction, gas_cost, mem_written, store_written)
}
fn trace_executed(&mut self, gas_used: U256, stack_push: &[U256], mem_diff: Option<(usize, &[u8])>, store_diff: Option<(U256, U256)>) {
self.vm_tracer.trace_executed(gas_used, stack_push, mem_diff, store_diff)
fn trace_executed(&mut self, gas_used: U256, stack_push: &[U256], mem: &[u8]) {
self.vm_tracer.trace_executed(gas_used, stack_push, mem)
}
}
@@ -480,8 +480,9 @@ mod tests {
let state = &mut setup.state;
let mut tracer = NoopTracer;
let mut vm_tracer = NoopVMTracer;
let origin_info = get_test_origin();
let ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
let ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, 0, &origin_info, &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
assert_eq!(ext.env_info().number, 100);
}
@@ -492,8 +493,9 @@ mod tests {
let state = &mut setup.state;
let mut tracer = NoopTracer;
let mut vm_tracer = NoopVMTracer;
let origin_info = get_test_origin();
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, 0, &origin_info, &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
let hash = ext.blockhash(&"0000000000000000000000000000000000000000000000000000000000120000".parse::<U256>().unwrap());
@@ -516,8 +518,9 @@ mod tests {
let state = &mut setup.state;
let mut tracer = NoopTracer;
let mut vm_tracer = NoopVMTracer;
let origin_info = get_test_origin();
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, 0, &origin_info, &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
let hash = ext.blockhash(&"0000000000000000000000000000000000000000000000000000000000120000".parse::<U256>().unwrap());
@@ -531,8 +534,9 @@ mod tests {
let state = &mut setup.state;
let mut tracer = NoopTracer;
let mut vm_tracer = NoopVMTracer;
let origin_info = get_test_origin();
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, 0, &origin_info, &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
// this should panic because we have no balance on any account
ext.call(
@@ -542,8 +546,9 @@ mod tests {
Some("0000000000000000000000000000000000000000000000000000000000150000".parse::<U256>().unwrap()),
&[],
&Address::new(),
CallType::Call
);
CallType::Call,
false,
).ok().unwrap();
}
#[test]
@@ -555,9 +560,10 @@ mod tests {
let state = &mut setup.state;
let mut tracer = NoopTracer;
let mut vm_tracer = NoopVMTracer;
let origin_info = get_test_origin();
{
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, 0, &origin_info, &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
ext.log(log_topics, &log_data).unwrap();
}
@@ -572,9 +578,10 @@ mod tests {
let state = &mut setup.state;
let mut tracer = NoopTracer;
let mut vm_tracer = NoopVMTracer;
let origin_info = get_test_origin();
{
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, 0, &origin_info, &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
ext.suicide(refund_account).unwrap();
}
@@ -589,11 +596,12 @@ mod tests {
let state = &mut setup.state;
let mut tracer = NoopTracer;
let mut vm_tracer = NoopVMTracer;
let origin_info = get_test_origin();
let address = {
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
match ext.create(&U256::max_value(), &U256::zero(), &[], CreateContractAddress::FromSenderAndNonce) {
ContractCreateResult::Created(address, _) => address,
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, 0, &origin_info, &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
match ext.create(&U256::max_value(), &U256::zero(), &[], CreateContractAddress::FromSenderAndNonce, false) {
Ok(ContractCreateResult::Created(address, _)) => address,
_ => panic!("Test create failed; expected Created, got Failed/Reverted."),
}
};
@@ -609,12 +617,13 @@ mod tests {
let state = &mut setup.state;
let mut tracer = NoopTracer;
let mut vm_tracer = NoopVMTracer;
let origin_info = get_test_origin();
let address = {
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, 0, &origin_info, &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
match ext.create(&U256::max_value(), &U256::zero(), &[], CreateContractAddress::FromSenderSaltAndCodeHash(H256::default())) {
ContractCreateResult::Created(address, _) => address,
match ext.create(&U256::max_value(), &U256::zero(), &[], CreateContractAddress::FromSenderSaltAndCodeHash(H256::default()), false) {
Ok(ContractCreateResult::Created(address, _)) => address,
_ => panic!("Test create failed; expected Created, got Failed/Reverted."),
}
};

View File

@@ -18,7 +18,7 @@ use trie::TrieFactory;
use ethtrie::RlpCodec;
use account_db::Factory as AccountFactory;
use evm::{Factory as EvmFactory, VMType};
use vm::{Vm, ActionParams, Schedule};
use vm::{Exec, ActionParams, Schedule};
use wasm::WasmInterpreter;
use keccak_hasher::KeccakHasher;
@@ -31,7 +31,7 @@ pub struct VmFactory {
}
impl VmFactory {
pub fn create(&self, params: ActionParams, schedule: &Schedule, depth: usize) -> Box<Vm> {
pub fn create(&self, params: ActionParams, schedule: &Schedule, depth: usize) -> Box<Exec> {
if schedule.wasm.is_some() && params.code.as_ref().map_or(false, |code| code.len() > 4 && &code[0..4] == WASM_MAGIC_NUMBER) {
Box::new(WasmInterpreter::new(params))
} else {

View File

@@ -449,7 +449,7 @@ mod tests {
let header_rlp = "f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23".from_hex().unwrap();
let header: Header = rlp::decode(&header_rlp).expect("error decoding header");
let encoded_header = rlp::encode(&header).into_vec();
let encoded_header = rlp::encode(&header);
assert_eq!(header_rlp, encoded_header);
}

View File

@@ -23,7 +23,8 @@ use miner::Miner;
use io::IoChannel;
use test_helpers;
use verification::queue::kind::blocks::Unverified;
use verification::VerifierType;
use super::SKIP_TEST_STATE;
use super::HookType;
/// Run chain jsontests on a given folder.
@@ -36,12 +37,20 @@ pub fn run_test_file<H: FnMut(&str, HookType)>(p: &Path, h: &mut H) {
::json_tests::test_common::run_test_file(p, json_chain_test, h)
}
fn skip_test(name: &String) -> bool {
SKIP_TEST_STATE.block.iter().any(|block_test|block_test.subtests.contains(name))
}
pub fn json_chain_test<H: FnMut(&str, HookType)>(json_data: &[u8], start_stop_hook: &mut H) -> Vec<String> {
::ethcore_logger::init_log();
let tests = ethjson::blockchain::Test::load(json_data).unwrap();
let mut failed = Vec::new();
for (name, blockchain) in tests.into_iter() {
if skip_test(&name) {
println!(" - {} | {:?} Ignoring tests because in skip list", name, blockchain.network);
continue;
}
start_stop_hook(&name, HookType::OnStart);
let mut fail = false;
@@ -75,6 +84,10 @@ pub fn json_chain_test<H: FnMut(&str, HookType)>(json_data: &[u8], start_stop_ho
{
let db = test_helpers::new_db();
let mut config = ClientConfig::default();
if ethjson::blockchain::Engine::NoProof == blockchain.engine {
config.verifier_type = VerifierType::CanonNoSeal;
config.check_seal = false;
}
config.history = 8;
let client = Client::new(
config,
@@ -122,19 +135,24 @@ mod block_tests {
declare_test!{BlockchainTests_bcInvalidHeaderTest, "BlockchainTests/bcInvalidHeaderTest"}
declare_test!{BlockchainTests_bcMultiChainTest, "BlockchainTests/bcMultiChainTest"}
declare_test!{BlockchainTests_bcRandomBlockhashTest, "BlockchainTests/bcRandomBlockhashTest"}
declare_test!{BlockchainTests_bcStateTest, "BlockchainTests/bcStateTests"}
declare_test!{BlockchainTests_bcTotalDifficultyTest, "BlockchainTests/bcTotalDifficultyTest"}
declare_test!{BlockchainTests_bcUncleHeaderValidity, "BlockchainTests/bcUncleHeaderValidity"}
declare_test!{BlockchainTests_bcUncleTest, "BlockchainTests/bcUncleTest"}
declare_test!{BlockchainTests_bcValidBlockTest, "BlockchainTests/bcValidBlockTest"}
declare_test!{BlockchainTests_bcWalletTest, "BlockchainTests/bcWalletTest"}
declare_test!{BlockchainTests_GeneralStateTest_stArgsZeroOneBalance, "BlockchainTests/GeneralStateTests/stArgsZeroOneBalance/"}
declare_test!{BlockchainTests_GeneralStateTest_stAttackTest, "BlockchainTests/GeneralStateTests/stAttackTest/"}
declare_test!{BlockchainTests_GeneralStateTest_stBadOpcodeTest, "BlockchainTests/GeneralStateTests/stBadOpcode/"}
declare_test!{BlockchainTests_GeneralStateTest_stBugsTest, "BlockchainTests/GeneralStateTests/stBugs/"}
declare_test!{BlockchainTests_GeneralStateTest_stCallCodes, "BlockchainTests/GeneralStateTests/stCallCodes/"}
declare_test!{BlockchainTests_GeneralStateTest_stCallCreateCallCodeTest, "BlockchainTests/GeneralStateTests/stCallCreateCallCodeTest/"}
declare_test!{BlockchainTests_GeneralStateTest_stCallDelegateCodesCallCodeHomestead, "BlockchainTests/GeneralStateTests/stCallDelegateCodesCallCodeHomestead/"}
declare_test!{BlockchainTests_GeneralStateTest_stCallDelegateCodesHomestead, "BlockchainTests/GeneralStateTests/stCallDelegateCodesHomestead/"}
declare_test!{BlockchainTests_GeneralStateTest_stChangedEIP150, "BlockchainTests/GeneralStateTests/stChangedEIP150/"}
declare_test!{BlockchainTests_GeneralStateTest_stCodeSizeLimit, "BlockchainTests/GeneralStateTests/stCodeSizeLimit/"}
declare_test!{BlockchainTests_GeneralStateTest_stCreate2, "BlockchainTests/GeneralStateTests/stCreate2/"}
declare_test!{BlockchainTests_GeneralStateTest_stCreateTest, "BlockchainTests/GeneralStateTests/stCreateTest/"}
declare_test!{BlockchainTests_GeneralStateTest_stDelegatecallTestHomestead, "BlockchainTests/GeneralStateTests/stDelegatecallTestHomestead/"}
declare_test!{BlockchainTests_GeneralStateTest_stEIP150singleCodeGasPrices, "BlockchainTests/GeneralStateTests/stEIP150singleCodeGasPrices/"}
@@ -149,12 +167,15 @@ mod block_tests {
declare_test!{BlockchainTests_GeneralStateTest_stMemoryTest, "BlockchainTests/GeneralStateTests/stMemoryTest/"}
declare_test!{BlockchainTests_GeneralStateTest_stNonZeroCallsTest, "BlockchainTests/GeneralStateTests/stNonZeroCallsTest/"}
declare_test!{BlockchainTests_GeneralStateTest_stPreCompiledContracts, "BlockchainTests/GeneralStateTests/stPreCompiledContracts/"}
declare_test!{BlockchainTests_GeneralStateTest_stPreCompiledContracts2, "BlockchainTests/GeneralStateTests/stPreCompiledContracts2/"}
declare_test!{heavy => BlockchainTests_GeneralStateTest_stQuadraticComplexityTest, "BlockchainTests/GeneralStateTests/stQuadraticComplexityTest/"}
declare_test!{BlockchainTests_GeneralStateTest_stRandom, "BlockchainTests/GeneralStateTests/stRandom/"}
declare_test!{BlockchainTests_GeneralStateTest_stRandom2, "BlockchainTests/GeneralStateTests/stRandom2/"}
declare_test!{BlockchainTests_GeneralStateTest_stRecursiveCreate, "BlockchainTests/GeneralStateTests/stRecursiveCreate/"}
declare_test!{BlockchainTests_GeneralStateTest_stRefundTest, "BlockchainTests/GeneralStateTests/stRefundTest/"}
declare_test!{BlockchainTests_GeneralStateTest_stReturnDataTest, "BlockchainTests/GeneralStateTests/stReturnDataTest/"}
declare_test!{BlockchainTests_GeneralStateTest_stRevertTest, "BlockchainTests/GeneralStateTests/stRevertTest/"}
declare_test!{BlockchainTests_GeneralStateTest_stShift, "BlockchainTests/GeneralStateTests/stShift/"}
declare_test!{BlockchainTests_GeneralStateTest_stSolidityTest, "BlockchainTests/GeneralStateTests/stSolidityTest/"}
declare_test!{BlockchainTests_GeneralStateTest_stSpecialTest, "BlockchainTests/GeneralStateTests/stSpecialTest/"}
declare_test!{BlockchainTests_GeneralStateTest_stStackTests, "BlockchainTests/GeneralStateTests/stStackTests/"}
@@ -166,6 +187,8 @@ mod block_tests {
declare_test!{BlockchainTests_GeneralStateTest_stZeroCallsRevert, "BlockchainTests/GeneralStateTests/stZeroCallsRevert/"}
declare_test!{BlockchainTests_GeneralStateTest_stZeroCallsTest, "BlockchainTests/GeneralStateTests/stZeroCallsTest/"}
declare_test!{BlockchainTests_GeneralStateTest_stZeroKnowledge, "BlockchainTests/GeneralStateTests/stZeroKnowledge/"}
declare_test!{BlockchainTests_GeneralStateTest_stZeroKnowledge2, "BlockchainTests/GeneralStateTests/stZeroKnowledge2/"}
declare_test!{BlockchainTests_GeneralStateTest_stSStoreTest, "BlockchainTests/GeneralStateTests/stSStoreTest/"}
declare_test!{BlockchainTests_TransitionTests_bcEIP158ToByzantium, "BlockchainTests/TransitionTests/bcEIP158ToByzantium/"}
declare_test!{BlockchainTests_TransitionTests_bcFrontierToHomestead, "BlockchainTests/TransitionTests/bcFrontierToHomestead/"}

View File

@@ -88,7 +88,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> TestExt<'a, T, V, B>
machine: &'a Machine,
schedule: &'a Schedule,
depth: usize,
origin_info: OriginInfo,
origin_info: &'a OriginInfo,
substate: &'a mut Substate,
output: OutputPolicy,
address: Address,
@@ -98,7 +98,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> TestExt<'a, T, V, B>
let static_call = false;
Ok(TestExt {
nonce: state.nonce(&address)?,
ext: Externalities::new(state, info, machine, schedule, depth, origin_info, substate, output, tracer, vm_tracer, static_call),
ext: Externalities::new(state, info, machine, schedule, depth, 0, origin_info, substate, output, tracer, vm_tracer, static_call),
callcreates: vec![],
sender: address,
})
@@ -140,7 +140,14 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for TestExt<'a, T, V, B>
self.ext.blockhash(number)
}
fn create(&mut self, gas: &U256, value: &U256, code: &[u8], address: CreateContractAddress) -> ContractCreateResult {
fn create(
&mut self,
gas: &U256,
value: &U256,
code: &[u8],
address: CreateContractAddress,
_trap: bool
) -> Result<ContractCreateResult, vm::TrapKind> {
self.callcreates.push(CallCreate {
data: code.to_vec(),
destination: None,
@@ -148,25 +155,27 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for TestExt<'a, T, V, B>
value: *value
});
let contract_address = contract_address(address, &self.sender, &self.nonce, &code).0;
ContractCreateResult::Created(contract_address, *gas)
Ok(ContractCreateResult::Created(contract_address, *gas))
}
fn call(&mut self,
fn call(
&mut self,
gas: &U256,
_sender_address: &Address,
receive_address: &Address,
value: Option<U256>,
data: &[u8],
_code_address: &Address,
_call_type: CallType
) -> MessageCallResult {
_call_type: CallType,
_trap: bool
) -> Result<MessageCallResult, vm::TrapKind> {
self.callcreates.push(CallCreate {
data: data.to_vec(),
destination: Some(receive_address.clone()),
gas_limit: *gas,
value: value.unwrap()
});
MessageCallResult::Success(*gas, ReturnData::empty())
Ok(MessageCallResult::Success(*gas, ReturnData::empty()))
}
fn extcode(&self, address: &Address) -> vm::Result<Option<Arc<Bytes>>> {
@@ -270,6 +279,7 @@ fn do_json_test_for<H: FnMut(&str, HookType)>(vm_type: &VMType, json_data: &[u8]
let mut tracer = NoopTracer;
let mut vm_tracer = NoopVMTracer;
let vm_factory = state.vm_factory();
let origin_info = OriginInfo::from(&params);
// execute
let (res, callcreates) = {
@@ -280,7 +290,7 @@ fn do_json_test_for<H: FnMut(&str, HookType)>(vm_type: &VMType, json_data: &[u8]
&machine,
&schedule,
0,
OriginInfo::from(&params),
&origin_info,
&mut substate,
OutputPolicy::Return,
params.address.clone(),
@@ -288,7 +298,7 @@ fn do_json_test_for<H: FnMut(&str, HookType)>(vm_type: &VMType, json_data: &[u8]
&mut vm_tracer,
));
let mut evm = vm_factory.create(params, &schedule, 0);
let res = evm.exec(&mut ex);
let res = evm.exec(&mut ex).ok().expect("TestExt never trap; resume error never happens; qed");
// a return in finalize will not alter callcreates
let callcreates = ex.callcreates.clone();
(res.finalize(ex), callcreates)

View File

@@ -24,10 +24,12 @@ mod executive;
mod state;
mod chain;
mod trie;
mod skip;
#[cfg(test)]
mod difficulty;
pub use self::test_common::HookType;
pub use self::transaction::run_test_path as run_transaction_test_path;
@@ -42,3 +44,4 @@ pub use self::trie::run_generic_test_path as run_generic_trie_test_path;
pub use self::trie::run_generic_test_file as run_generic_trie_test_file;
pub use self::trie::run_secure_test_path as run_secure_trie_test_path;
pub use self::trie::run_secure_test_file as run_secure_trie_test_file;
use self::skip::SKIP_TEST_STATE;

View File

@@ -0,0 +1,37 @@
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! State tests to skip.
use ethjson;
#[cfg(all(not(test), feature = "ci-skip-tests"))]
compile_error!("ci-skip-tests can only be enabled for testing builds.");
#[cfg(feature="ci-skip-issue")]
lazy_static!{
pub static ref SKIP_TEST_STATE: ethjson::test::SkipStates = {
let skip_data = include_bytes!("../../res/ethereum/tests-issues/currents.json");
ethjson::test::SkipStates::load(&skip_data[..]).expect("No invalid json allowed")
};
}
#[cfg(not(feature="ci-skip-issue"))]
lazy_static!{
pub static ref SKIP_TEST_STATE: ethjson::test::SkipStates = {
ethjson::test::SkipStates::empty()
};
}

View File

@@ -22,7 +22,7 @@ use client::{EvmTestClient, EvmTestError, TransactResult};
use ethjson;
use transaction::SignedTransaction;
use vm::EnvInfo;
use super::SKIP_TEST_STATE;
use super::HookType;
/// Run state jsontests on a given folder.
@@ -35,6 +35,18 @@ pub fn run_test_file<H: FnMut(&str, HookType)>(p: &Path, h: &mut H) {
::json_tests::test_common::run_test_file(p, json_chain_test, h)
}
fn skip_test(subname: &str, chain: &String, number: usize) -> bool {
SKIP_TEST_STATE.state.iter().any(|state_test|{
if let Some(subtest) = state_test.subtests.get(subname) {
chain == &subtest.chain &&
(subtest.subnumbers[0] == "*"
|| subtest.subnumbers.contains(&number.to_string()))
} else {
false
}
})
}
pub fn json_chain_test<H: FnMut(&str, HookType)>(json_data: &[u8], start_stop_hook: &mut H) -> Vec<String> {
::ethcore_logger::init_log();
let tests = ethjson::state::test::Test::load(json_data).unwrap();
@@ -60,6 +72,10 @@ pub fn json_chain_test<H: FnMut(&str, HookType)>(json_data: &[u8], start_stop_ho
for (i, state) in states.into_iter().enumerate() {
let info = format!(" - {} | {:?} ({}/{}) ...", name, spec_name, i + 1, total);
if skip_test(&name, &spec.name, i + 1) {
println!("{} in skip list : SKIPPED", info);
continue;
}
let post_root: H256 = state.hash.into();
let transaction: SignedTransaction = multitransaction.select(&state.indexes).into();
@@ -125,11 +141,13 @@ mod state_tests {
declare_test!{GeneralStateTest_stChangedEIP150, "GeneralStateTests/stChangedEIP150/"}
declare_test!{GeneralStateTest_stCodeCopyTest, "GeneralStateTests/stCodeCopyTest/"}
declare_test!{GeneralStateTest_stCodeSizeLimit, "GeneralStateTests/stCodeSizeLimit/"}
declare_test!{GeneralStateTest_stCreate2Test, "GeneralStateTests/stCreate2/"}
declare_test!{GeneralStateTest_stCreateTest, "GeneralStateTests/stCreateTest/"}
declare_test!{GeneralStateTest_stDelegatecallTestHomestead, "GeneralStateTests/stDelegatecallTestHomestead/"}
declare_test!{GeneralStateTest_stEIP150singleCodeGasPrices, "GeneralStateTests/stEIP150singleCodeGasPrices/"}
declare_test!{GeneralStateTest_stEIP150Specific, "GeneralStateTests/stEIP150Specific/"}
declare_test!{GeneralStateTest_stEIP158Specific, "GeneralStateTests/stEIP158Specific/"}
declare_test!{GeneralStateTest_stEWASMTests, "GeneralStateTests/stEWASMTests/"}
declare_test!{GeneralStateTest_stExample, "GeneralStateTests/stExample/"}
declare_test!{GeneralStateTest_stHomesteadSpecific, "GeneralStateTests/stHomesteadSpecific/"}
declare_test!{GeneralStateTest_stInitCodeTest, "GeneralStateTests/stInitCodeTest/"}
@@ -159,6 +177,7 @@ mod state_tests {
declare_test!{GeneralStateTest_stZeroCallsRevert, "GeneralStateTests/stZeroCallsRevert/"}
declare_test!{GeneralStateTest_stZeroCallsTest, "GeneralStateTests/stZeroCallsTest/"}
declare_test!{GeneralStateTest_stZeroKnowledge, "GeneralStateTests/stZeroKnowledge/"}
declare_test!{GeneralStateTest_stSStoreTest, "GeneralStateTests/stSStoreTest/"}
// Attempts to send a transaction that requires more than current balance:
// Tx:

View File

@@ -34,6 +34,18 @@ pub fn run_test_path<H: FnMut(&str, HookType)>(
p: &Path, skip: &[&'static str],
runner: fn(json_data: &[u8], start_stop_hook: &mut H) -> Vec<String>,
start_stop_hook: &mut H
) {
let mut errors = Vec::new();
run_test_path_inner(p, skip, runner, start_stop_hook, &mut errors);
let empty: [String; 0] = [];
assert_eq!(errors, empty);
}
fn run_test_path_inner<H: FnMut(&str, HookType)>(
p: &Path, skip: &[&'static str],
runner: fn(json_data: &[u8], start_stop_hook: &mut H) -> Vec<String>,
start_stop_hook: &mut H,
errors: &mut Vec<String>
) {
let path = Path::new(p);
let s: HashSet<OsString> = skip.iter().map(|s| {
@@ -50,17 +62,32 @@ pub fn run_test_path<H: FnMut(&str, HookType)>(
} else {
Some(e.path())
}}) {
run_test_path(&p, skip, runner, start_stop_hook)
run_test_path_inner(&p, skip, runner, start_stop_hook, errors);
}
} else if extension == Some("swp") || extension == None {
// Ignore junk
} else {
let mut path = p.to_path_buf();
path.set_extension("json");
run_test_file(&path, runner, start_stop_hook)
run_test_file_append(&path, runner, start_stop_hook, errors)
}
}
fn run_test_file_append<H: FnMut(&str, HookType)>(
path: &Path,
runner: fn(json_data: &[u8], start_stop_hook: &mut H) -> Vec<String>,
start_stop_hook: &mut H,
errors: &mut Vec<String>
) {
let mut data = Vec::new();
let mut file = match File::open(&path) {
Ok(file) => file,
Err(_) => panic!("Error opening test file at: {:?}", path),
};
file.read_to_end(&mut data).expect("Error reading test file");
errors.append(&mut runner(&data, start_stop_hook));
}
pub fn run_test_file<H: FnMut(&str, HookType)>(
path: &Path,
runner: fn(json_data: &[u8], start_stop_hook: &mut H) -> Vec<String>,

View File

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

View File

@@ -139,6 +139,9 @@ extern crate trace_time;
#[cfg_attr(test, macro_use)]
extern crate evm;
#[cfg(test)]
extern crate env_logger;
pub extern crate ethstore;
#[macro_use]
@@ -159,6 +162,7 @@ pub mod header;
pub mod machine;
pub mod miner;
pub mod pod_state;
pub mod pod_account;
pub mod snapshot;
pub mod spec;
pub mod state;
@@ -167,7 +171,6 @@ pub mod trace;
pub mod verification;
mod cache_manager;
mod pod_account;
mod account_db;
mod externalities;
mod blockchain;

View File

@@ -371,11 +371,11 @@ impl EthereumMachine {
}
/// Does verification of the transaction against the parent state.
pub fn verify_transaction<C: BlockInfo + CallContract>(&self, t: &SignedTransaction, header: &Header, client: &C)
pub fn verify_transaction<C: BlockInfo + CallContract>(&self, t: &SignedTransaction, parent: &Header, client: &C)
-> Result<(), transaction::Error>
{
if let Some(ref filter) = self.tx_filter.as_ref() {
if !filter.transaction_allowed(header.parent_hash(), header.number(), t, client) {
if !filter.transaction_allowed(&parent.hash(), parent.number() + 1, t, client) {
return Err(transaction::Error::NotAllowed.into())
}
}

View File

@@ -50,7 +50,7 @@ use executive::contract_address;
use header::{Header, BlockNumber};
use miner;
use miner::pool_client::{PoolClient, CachedNonceClient, NonceCache};
use receipt::{Receipt, RichReceipt};
use receipt::RichReceipt;
use spec::Spec;
use state::State;
use ethkey::Password;
@@ -576,10 +576,9 @@ impl Miner {
trace!(target: "miner", "requires_reseal: sealing enabled");
// Disable sealing if there were no requests for SEALING_TIMEOUT_IN_BLOCKS
let had_requests = sealing.last_request.map(|last_request| {
best_block > last_request
&& best_block - last_request <= SEALING_TIMEOUT_IN_BLOCKS
}).unwrap_or(false);
let had_requests = sealing.last_request.map(|last_request|
best_block.saturating_sub(last_request) <= SEALING_TIMEOUT_IN_BLOCKS
).unwrap_or(false);
// keep sealing enabled if any of the conditions is met
let sealing_enabled = self.forced_sealing()
@@ -938,6 +937,10 @@ impl miner::MinerService for Miner {
self.transaction_queue.all_transactions()
}
fn queued_transaction_hashes(&self) -> Vec<H256> {
self.transaction_queue.all_transaction_hashes()
}
fn pending_transaction_hashes<C>(&self, chain: &C) -> BTreeSet<H256> where
C: ChainInfo + Sync,
{
@@ -1039,19 +1042,17 @@ impl miner::MinerService for Miner {
self.transaction_queue.status()
}
fn pending_receipt(&self, best_block: BlockNumber, hash: &H256) -> Option<RichReceipt> {
fn pending_receipts(&self, best_block: BlockNumber) -> Option<Vec<RichReceipt>> {
self.map_existing_pending_block(|pending| {
let txs = pending.transactions();
txs.iter()
.map(|t| t.hash())
.position(|t| t == *hash)
.map(|index| {
let receipts = pending.receipts();
let receipts = pending.receipts();
pending.transactions()
.into_iter()
.enumerate()
.map(|(index, tx)| {
let prev_gas = if index == 0 { Default::default() } else { receipts[index - 1].gas_used };
let tx = &txs[index];
let receipt = &receipts[index];
RichReceipt {
transaction_hash: hash.clone(),
transaction_hash: tx.hash(),
transaction_index: index,
cumulative_gas_used: receipt.gas_used,
gas_used: receipt.gas_used - prev_gas,
@@ -1067,15 +1068,7 @@ impl miner::MinerService for Miner {
outcome: receipt.outcome.clone(),
}
})
}, best_block).and_then(|x| x)
}
fn pending_receipts(&self, best_block: BlockNumber) -> Option<BTreeMap<H256, Receipt>> {
self.map_existing_pending_block(|pending| {
let hashes = pending.transactions().iter().map(|t| t.hash());
let receipts = pending.receipts().iter().cloned();
hashes.zip(receipts).collect()
.collect()
}, best_block)
}
@@ -1400,6 +1393,33 @@ mod tests {
assert_eq!(miner.prepare_pending_block(&client), BlockPreparationStatus::NotPrepared);
}
#[test]
fn should_not_return_stale_work_packages() {
// given
let client = TestBlockChainClient::default();
let miner = miner();
// initial work package should create the pending block
let res = miner.work_package(&client);
assert_eq!(res.unwrap().1, 1);
// This should be true, since there were some requests.
assert_eq!(miner.requires_reseal(0), true);
// when new block is imported
let client = generate_dummy_client(2);
let imported = [0.into()];
let empty = &[];
miner.chain_new_blocks(&*client, &imported, empty, &imported, empty, false);
// then
// This should be false, because it's too early.
assert_eq!(miner.requires_reseal(2), false);
// but still work package should be ready
let res = miner.work_package(&*client);
assert_eq!(res.unwrap().1, 3);
assert_eq!(miner.prepare_pending_block(&*client), BlockPreparationStatus::NotPrepared);
}
#[test]
fn should_not_use_pending_block_if_best_block_is_higher() {
// given

View File

@@ -44,7 +44,7 @@ use client::{
};
use error::Error;
use header::{BlockNumber, Header};
use receipt::{RichReceipt, Receipt};
use receipt::RichReceipt;
use transaction::{self, UnverifiedTransaction, SignedTransaction, PendingTransaction};
use state::StateInfo;
use ethkey::Password;
@@ -95,10 +95,13 @@ pub trait MinerService : Send + Sync {
// Pending block
/// Get a list of all pending receipts from pending block.
fn pending_receipts(&self, best_block: BlockNumber) -> Option<BTreeMap<H256, Receipt>>;
fn pending_receipts(&self, best_block: BlockNumber) -> Option<Vec<RichReceipt>>;
/// Get a particular receipt from pending block.
fn pending_receipt(&self, best_block: BlockNumber, hash: &H256) -> Option<RichReceipt>;
fn pending_receipt(&self, best_block: BlockNumber, hash: &H256) -> Option<RichReceipt> {
let receipts = self.pending_receipts(best_block)?;
receipts.into_iter().find(|r| &r.transaction_hash == hash)
}
/// Get `Some` `clone()` of the current pending block's state or `None` if we're not sealing.
fn pending_state(&self, latest_block_number: BlockNumber) -> Option<Self::State>;
@@ -182,6 +185,9 @@ pub trait MinerService : Send + Sync {
/// Get a list of all transactions in the pool (some of them might not be ready for inclusion yet).
fn queued_transactions(&self) -> Vec<Arc<VerifiedTransaction>>;
/// Get a list of all transaction hashes in the pool (some of them might not be ready for inclusion yet).
fn queued_transaction_hashes(&self) -> Vec<H256>;
/// Get a list of local transactions with statuses.
fn local_transactions(&self) -> BTreeMap<H256, local_transactions::Status>;

View File

@@ -18,16 +18,15 @@
use client::{RegistryInfo, CallContract, BlockId};
use transaction::SignedTransaction;
use ethabi::FunctionOutputDecoder;
use_contract!(service_transaction, "ServiceTransaction", "res/contracts/service_transaction.json");
use_contract!(service_transaction, "res/contracts/service_transaction.json");
const SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME: &'static str = "service_transaction_checker";
/// Service transactions checker.
#[derive(Default, Clone)]
pub struct ServiceTransactionChecker {
contract: service_transaction::ServiceTransaction,
}
pub struct ServiceTransactionChecker;
impl ServiceTransactionChecker {
/// Checks if given address is whitelisted to send service transactions.
@@ -45,9 +44,8 @@ impl ServiceTransactionChecker {
trace!(target: "txqueue", "[{:?}] Checking service transaction checker contract from {}", hash, sender);
self.contract.functions()
.certified()
.call(sender, &|data| client.call_contract(BlockId::Latest, address, data))
.map_err(|e| e.to_string())
let (data, decoder) = service_transaction::functions::certified::call(sender);
let value = client.call_contract(BlockId::Latest, address, data)?;
decoder.decode(&value).map_err(|e| e.to_string())
}
}

View File

@@ -138,7 +138,7 @@ impl JobDispatcher for StratumJobDispatcher {
);
self.with_core_result(|client, miner| {
let seal = vec![encode(&payload.mix_hash).into_vec(), encode(&payload.nonce).into_vec()];
let seal = vec![encode(&payload.mix_hash), encode(&payload.nonce)];
let import = miner.submit_seal(payload.pow_hash, seal)
.and_then(|block| client.import_sealed_block(block));

View File

@@ -14,12 +14,15 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Account system expressed in Plain Old Data.
use std::fmt;
use std::collections::BTreeMap;
use itertools::Itertools;
use hash::{keccak};
use ethereum_types::{H256, U256};
use hashdb::HashDB;
use kvdb::DBValue;
use keccak_hasher::KeccakHasher;
use triehash::sec_trie_root;
use bytes::Bytes;
@@ -67,7 +70,7 @@ impl PodAccount {
}
/// Place additional data into given hash DB.
pub fn insert_additional(&self, db: &mut HashDB<KeccakHasher>, factory: &TrieFactory<KeccakHasher, RlpCodec>) {
pub fn insert_additional(&self, db: &mut HashDB<KeccakHasher, DBValue>, factory: &TrieFactory<KeccakHasher, RlpCodec>) {
match self.code {
Some(ref c) if !c.is_empty() => { db.insert(c); }
_ => {}

View File

@@ -123,7 +123,7 @@ pub fn to_fat_rlps(account_hash: &H256, acc: &BasicAccount, acct_db: &AccountDB,
let stream = ::std::mem::replace(&mut account_stream, RlpStream::new_list(2));
chunks.push(stream.out());
target_chunk_size = max_chunk_size;
leftover = Some(pair.into_vec());
leftover = Some(pair);
break;
}
},

View File

@@ -65,6 +65,8 @@ pub enum Error {
BadEpochProof(u64),
/// Wrong chunk format.
WrongChunkFormat(String),
/// Unlinked ancient block chain
UnlinkedAncientBlockChain,
}
impl fmt::Display for Error {
@@ -91,6 +93,7 @@ impl fmt::Display for Error {
Error::SnapshotsUnsupported => write!(f, "Snapshots unsupported by consensus engine."),
Error::BadEpochProof(i) => write!(f, "Bad epoch proof for transition to epoch {}", i),
Error::WrongChunkFormat(ref msg) => write!(f, "Wrong chunk format: {}", msg),
Error::UnlinkedAncientBlockChain => write!(f, "Unlinked ancient blocks chain"),
}
}
}

View File

@@ -34,12 +34,11 @@ use ids::BlockId;
use ethereum_types::{H256, U256};
use hashdb::HashDB;
use keccak_hasher::KeccakHasher;
use kvdb::DBValue;
use snappy;
use bytes::Bytes;
use parking_lot::Mutex;
use journaldb::{self, Algorithm, JournalDB};
use kvdb::KeyValueDB;
use kvdb::{KeyValueDB, DBValue};
use trie::{Trie, TrieMut};
use ethtrie::{TrieDB, TrieDBMut};
use rlp::{RlpStream, Rlp};
@@ -57,7 +56,7 @@ use rand::{Rng, OsRng};
pub use self::error::Error;
pub use self::consensus::*;
pub use self::service::{Service, DatabaseRestore};
pub use self::service::{SnapshotClient, Service, DatabaseRestore};
pub use self::traits::SnapshotService;
pub use self::watcher::Watcher;
pub use types::snapshot_manifest::ManifestData;
@@ -152,7 +151,7 @@ pub fn take_snapshot<W: SnapshotWriter + Send>(
engine: &EthEngine,
chain: &BlockChain,
block_at: H256,
state_db: &HashDB<KeccakHasher>,
state_db: &HashDB<KeccakHasher, DBValue>,
writer: W,
p: &Progress,
processing_threads: usize,
@@ -322,7 +321,7 @@ impl<'a> StateChunker<'a> {
///
/// Returns a list of hashes of chunks created, or any error it may
/// have encountered.
pub fn chunk_state<'a>(db: &HashDB<KeccakHasher>, root: &H256, writer: &Mutex<SnapshotWriter + 'a>, progress: &'a Progress, part: Option<usize>) -> Result<Vec<H256>, Error> {
pub fn chunk_state<'a>(db: &HashDB<KeccakHasher, DBValue>, root: &H256, writer: &Mutex<SnapshotWriter + 'a>, progress: &'a Progress, part: Option<usize>) -> Result<Vec<H256>, Error> {
let account_trie = TrieDB::new(db, &root)?;
let mut chunker = StateChunker {
@@ -494,7 +493,7 @@ struct RebuiltStatus {
// rebuild a set of accounts and their storage.
// returns a status detailing newly-loaded code and accounts missing code.
fn rebuild_accounts(
db: &mut HashDB<KeccakHasher>,
db: &mut HashDB<KeccakHasher, DBValue>,
account_fat_rlps: Rlp,
out_chunk: &mut [(H256, Bytes)],
known_code: &HashMap<H256, H256>,
@@ -541,7 +540,7 @@ fn rebuild_accounts(
}
}
::rlp::encode(&acc).into_vec()
::rlp::encode(&acc)
};
*out = (hash, thin_rlp);

View File

@@ -22,12 +22,13 @@ use std::fs::{self, File};
use std::path::PathBuf;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::cmp;
use super::{ManifestData, StateRebuilder, Rebuilder, RestorationStatus, SnapshotService, MAX_CHUNK_SIZE};
use super::io::{SnapshotReader, LooseReader, SnapshotWriter, LooseWriter};
use blockchain::{BlockChain, BlockChainDB, BlockChainDBHandler};
use client::{Client, ChainInfo, ClientIoMessage};
use client::{BlockInfo, BlockChainClient, Client, ChainInfo, ClientIoMessage};
use engines::EthEngine;
use error::{Error, ErrorKind as SnapshotErrorKind};
use snapshot::{Error as SnapshotError};
@@ -40,6 +41,7 @@ use ethereum_types::H256;
use parking_lot::{Mutex, RwLock, RwLockReadGuard};
use bytes::Bytes;
use journaldb::Algorithm;
use kvdb::DBTransaction;
use snappy;
/// Helper for removing directories in case of error.
@@ -203,6 +205,9 @@ impl Restoration {
/// Type alias for client io channel.
pub type Channel = IoChannel<ClientIoMessage>;
/// Trait alias for the Client Service used
pub trait SnapshotClient: BlockChainClient + BlockInfo + DatabaseRestore {}
/// Snapshot service parameters.
pub struct ServiceParams {
/// The consensus engine this is built on.
@@ -219,7 +224,7 @@ pub struct ServiceParams {
/// Usually "<chain hash>/snapshot"
pub snapshot_root: PathBuf,
/// A handle for database restoration.
pub db_restore: Arc<DatabaseRestore>,
pub client: Arc<SnapshotClient>,
}
/// `SnapshotService` implementation.
@@ -236,7 +241,7 @@ pub struct Service {
genesis_block: Bytes,
state_chunks: AtomicUsize,
block_chunks: AtomicUsize,
db_restore: Arc<DatabaseRestore>,
client: Arc<SnapshotClient>,
progress: super::Progress,
taking_snapshot: AtomicBool,
restoring_snapshot: AtomicBool,
@@ -257,7 +262,7 @@ impl Service {
genesis_block: params.genesis_block,
state_chunks: AtomicUsize::new(0),
block_chunks: AtomicUsize::new(0),
db_restore: params.db_restore,
client: params.client,
progress: Default::default(),
taking_snapshot: AtomicBool::new(false),
restoring_snapshot: AtomicBool::new(false),
@@ -334,12 +339,110 @@ impl Service {
// replace one the client's database with our own.
fn replace_client_db(&self) -> Result<(), Error> {
let our_db = self.restoration_db();
let migrated_blocks = self.migrate_blocks()?;
trace!(target: "snapshot", "Migrated {} ancient blocks", migrated_blocks);
self.db_restore.restore_db(&*our_db.to_string_lossy())?;
let rest_db = self.restoration_db();
self.client.restore_db(&*rest_db.to_string_lossy())?;
Ok(())
}
// Migrate the blocks in the current DB into the new chain
fn migrate_blocks(&self) -> Result<usize, Error> {
// Count the number of migrated blocks
let mut count = 0;
let rest_db = self.restoration_db();
let cur_chain_info = self.client.chain_info();
let next_db = self.restoration_db_handler.open(&rest_db)?;
let next_chain = BlockChain::new(Default::default(), &[], next_db.clone());
let next_chain_info = next_chain.chain_info();
// The old database looks like this:
// [genesis, best_ancient_block] ... [first_block, best_block]
// If we are fully synced neither `best_ancient_block` nor `first_block` is set, and we can assume that the whole range from [genesis, best_block] is imported.
// The new database only contains the tip of the chain ([first_block, best_block]),
// so the useful set of blocks is defined as:
// [0 ... min(new.first_block, best_ancient_block or best_block)]
let find_range = || -> Option<(H256, H256)> {
let next_available_from = next_chain_info.first_block_number?;
let cur_available_to = cur_chain_info.ancient_block_number.unwrap_or(cur_chain_info.best_block_number);
let highest_block_num = cmp::min(next_available_from.saturating_sub(1), cur_available_to);
if highest_block_num == 0 {
return None;
}
trace!(target: "snapshot", "Trying to import ancient blocks until {}", highest_block_num);
// Here we start from the highest block number and go backward to 0,
// thus starting at `highest_block_num` and targetting `0`.
let target_hash = self.client.block_hash(BlockId::Number(0))?;
let start_hash = self.client.block_hash(BlockId::Number(highest_block_num))?;
Some((start_hash, target_hash))
};
let (start_hash, target_hash) = match find_range() {
Some(x) => x,
None => return Ok(0),
};
let mut batch = DBTransaction::new();
let mut parent_hash = start_hash;
while parent_hash != target_hash {
// Early return if restoration is aborted
if !self.restoring_snapshot.load(Ordering::SeqCst) {
return Ok(count);
}
let block = self.client.block(BlockId::Hash(parent_hash)).ok_or(::snapshot::error::Error::UnlinkedAncientBlockChain)?;
parent_hash = block.parent_hash();
let block_number = block.number();
let block_receipts = self.client.block_receipts(&block.hash());
let parent_total_difficulty = self.client.block_total_difficulty(BlockId::Hash(parent_hash));
match (block_receipts, parent_total_difficulty) {
(Some(block_receipts), Some(parent_total_difficulty)) => {
let block_receipts = block_receipts.receipts;
next_chain.insert_unordered_block(&mut batch, block, block_receipts, Some(parent_total_difficulty), false, true);
count += 1;
},
_ => break,
}
// Writting changes to DB and logging every now and then
if block_number % 1_000 == 0 {
next_db.key_value().write_buffered(batch);
next_chain.commit();
next_db.key_value().flush().expect("DB flush failed.");
batch = DBTransaction::new();
}
if block_number % 10_000 == 0 {
trace!(target: "snapshot", "Block restoration at #{}", block_number);
}
}
// Final commit to the DB
next_db.key_value().write_buffered(batch);
next_chain.commit();
next_db.key_value().flush().expect("DB flush failed.");
// We couldn't reach the targeted hash
if parent_hash != target_hash {
return Err(::snapshot::error::Error::UnlinkedAncientBlockChain.into());
}
// Update best ancient block in the Next Chain
next_chain.update_best_ancient_block(&start_hash);
Ok(count)
}
/// Get a reference to the snapshot reader.
pub fn reader(&self) -> RwLockReadGuard<Option<LooseReader>> {
self.reader.read()
@@ -480,12 +583,16 @@ impl Service {
// Import previous chunks, continue if it fails
self.import_prev_chunks(&mut res, manifest).ok();
*self.status.lock() = RestorationStatus::Ongoing {
state_chunks: state_chunks as u32,
block_chunks: block_chunks as u32,
state_chunks_done: self.state_chunks.load(Ordering::SeqCst) as u32,
block_chunks_done: self.block_chunks.load(Ordering::SeqCst) as u32,
};
// It could be that the restoration failed or completed in the meanwhile
let mut restoration_status = self.status.lock();
if let RestorationStatus::Initializing { .. } = *restoration_status {
*restoration_status = RestorationStatus::Ongoing {
state_chunks: state_chunks as u32,
block_chunks: block_chunks as u32,
state_chunks_done: self.state_chunks.load(Ordering::SeqCst) as u32,
block_chunks_done: self.block_chunks.load(Ordering::SeqCst) as u32,
};
}
Ok(())
}
@@ -752,26 +859,19 @@ impl Drop for Service {
#[cfg(test)]
mod tests {
use std::sync::Arc;
use client::ClientIoMessage;
use io::{IoService};
use spec::Spec;
use journaldb::Algorithm;
use error::Error;
use snapshot::{ManifestData, RestorationStatus, SnapshotService};
use super::*;
use tempdir::TempDir;
use test_helpers::restoration_db_handler;
struct NoopDBRestore;
impl DatabaseRestore for NoopDBRestore {
fn restore_db(&self, _new_db: &str) -> Result<(), Error> {
Ok(())
}
}
use test_helpers::{generate_dummy_client_with_spec_and_data, restoration_db_handler};
#[test]
fn sends_async_messages() {
let gas_prices = vec![1.into(), 2.into(), 3.into(), 999.into()];
let client = generate_dummy_client_with_spec_and_data(Spec::new_null, 400, 5, &gas_prices);
let service = IoService::<ClientIoMessage>::start().unwrap();
let spec = Spec::new_test();
@@ -785,7 +885,7 @@ mod tests {
pruning: Algorithm::Archive,
channel: service.channel(),
snapshot_root: dir,
db_restore: Arc::new(NoopDBRestore),
client: client,
};
let service = Service::new(snapshot_params).unwrap();

View File

@@ -62,7 +62,7 @@ impl StateProducer {
/// Tick the state producer. This alters the state, writing new data into
/// the database.
pub fn tick<R: Rng>(&mut self, rng: &mut R, db: &mut HashDB<KeccakHasher>) {
pub fn tick<R: Rng>(&mut self, rng: &mut R, db: &mut HashDB<KeccakHasher, DBValue>) {
// modify existing accounts.
let mut accounts_to_modify: Vec<_> = {
let trie = TrieDB::new(&*db, &self.state_root).unwrap();
@@ -80,7 +80,7 @@ impl StateProducer {
let mut account: BasicAccount = ::rlp::decode(&*account_data).expect("error decoding basic account");
let acct_db = AccountDBMut::from_hash(db, *address_hash);
fill_storage(acct_db, &mut account.storage_root, &mut self.storage_seed);
*account_data = DBValue::from_vec(::rlp::encode(&account).into_vec());
*account_data = DBValue::from_vec(::rlp::encode(&account));
}
// sweep again to alter account trie.
@@ -131,7 +131,7 @@ pub fn fill_storage(mut db: AccountDBMut, root: &mut H256, seed: &mut H256) {
}
/// Compare two state dbs.
pub fn compare_dbs(one: &HashDB<KeccakHasher>, two: &HashDB<KeccakHasher>) {
pub fn compare_dbs(one: &HashDB<KeccakHasher, DBValue>, two: &HashDB<KeccakHasher, DBValue>) {
let keys = one.keys();
for key in keys.keys() {

View File

@@ -32,7 +32,7 @@ use tempdir::TempDir;
use ethereum_types::Address;
use test_helpers;
use_contract!(test_validator_set, "ValidatorSet", "res/contracts/test_validator_set.json");
use_contract!(test_validator_set, "res/contracts/test_validator_set.json");
const PASS: &'static str = "";
const TRANSITION_BLOCK_1: usize = 2; // block at which the contract becomes activated.
@@ -135,8 +135,6 @@ fn make_chain(accounts: Arc<AccountProvider>, blocks_beyond: usize, transitions:
vec![transaction]
};
let contract = test_validator_set::ValidatorSet::default();
// apply all transitions.
for transition in transitions {
let (num, manual, new_set) = match transition {
@@ -163,7 +161,7 @@ fn make_chain(accounts: Arc<AccountProvider>, blocks_beyond: usize, transitions:
false => &CONTRACT_ADDR_1 as &Address,
};
let data = contract.functions().set_validators().input(new_set.clone());
let data = test_validator_set::functions::set_validators::encode_input(new_set.clone());
let mut nonce = nonce.borrow_mut();
let transaction = Transaction {
nonce: *nonce,

View File

@@ -16,26 +16,23 @@
//! Tests for the snapshot service.
use std::fs;
use std::sync::Arc;
use tempdir::TempDir;
use client::{Client, BlockInfo};
use blockchain::BlockProvider;
use client::{Client, ClientConfig, ImportBlock, BlockInfo};
use ids::BlockId;
use snapshot::io::{PackedReader, PackedWriter, SnapshotReader, SnapshotWriter};
use snapshot::service::{Service, ServiceParams};
use snapshot::{self, ManifestData, SnapshotService};
use snapshot::{chunk_state, chunk_secondary, ManifestData, Progress, SnapshotService, RestorationStatus};
use spec::Spec;
use test_helpers::{generate_dummy_client_with_spec_and_data, restoration_db_handler};
use test_helpers::{new_db, new_temp_db, generate_dummy_client_with_spec_and_data, restoration_db_handler};
use parking_lot::Mutex;
use io::IoChannel;
use kvdb_rocksdb::DatabaseConfig;
struct NoopDBRestore;
impl snapshot::DatabaseRestore for NoopDBRestore {
fn restore_db(&self, _new_db: &str) -> Result<(), ::error::Error> {
Ok(())
}
}
use verification::queue::kind::blocks::Unverified;
#[test]
fn restored_is_equivalent() {
@@ -46,7 +43,6 @@ fn restored_is_equivalent() {
const TX_PER: usize = 5;
let gas_prices = vec![1.into(), 2.into(), 3.into(), 999.into()];
let client = generate_dummy_client_with_spec_and_data(Spec::new_null, NUM_BLOCKS, TX_PER, &gas_prices);
let tempdir = TempDir::new("").unwrap();
@@ -73,7 +69,7 @@ fn restored_is_equivalent() {
pruning: ::journaldb::Algorithm::Archive,
channel: IoChannel::disconnected(),
snapshot_root: path,
db_restore: client2.clone(),
client: client2.clone(),
};
let service = Service::new(service_params).unwrap();
@@ -94,7 +90,7 @@ fn restored_is_equivalent() {
service.feed_block_chunk(hash, &chunk);
}
assert_eq!(service.status(), ::snapshot::RestorationStatus::Inactive);
assert_eq!(service.status(), RestorationStatus::Inactive);
for x in 0..NUM_BLOCKS {
let block1 = client.block(BlockId::Number(x as u64)).unwrap();
@@ -106,6 +102,9 @@ fn restored_is_equivalent() {
#[test]
fn guards_delete_folders() {
let gas_prices = vec![1.into(), 2.into(), 3.into(), 999.into()];
let client = generate_dummy_client_with_spec_and_data(Spec::new_null, 400, 5, &gas_prices);
let spec = Spec::new_null();
let tempdir = TempDir::new("").unwrap();
let service_params = ServiceParams {
@@ -115,7 +114,7 @@ fn guards_delete_folders() {
pruning: ::journaldb::Algorithm::Archive,
channel: IoChannel::disconnected(),
snapshot_root: tempdir.path().to_owned(),
db_restore: Arc::new(NoopDBRestore),
client: client,
};
let service = Service::new(service_params).unwrap();
@@ -146,3 +145,201 @@ fn guards_delete_folders() {
assert!(!path.join("db").exists());
assert!(path.join("temp").exists());
}
#[test]
fn keep_ancient_blocks() {
::env_logger::init().ok();
// Test variables
const NUM_BLOCKS: u64 = 500;
const NUM_SNAPSHOT_BLOCKS: u64 = 300;
const SNAPSHOT_MODE: ::snapshot::PowSnapshot = ::snapshot::PowSnapshot { blocks: NUM_SNAPSHOT_BLOCKS, max_restore_blocks: NUM_SNAPSHOT_BLOCKS };
// Temporary folders
let tempdir = TempDir::new("").unwrap();
let snapshot_path = tempdir.path().join("SNAP");
// Generate blocks
let gas_prices = vec![1.into(), 2.into(), 3.into(), 999.into()];
let spec_f = Spec::new_null;
let spec = spec_f();
let client = generate_dummy_client_with_spec_and_data(spec_f, NUM_BLOCKS as u32, 5, &gas_prices);
let bc = client.chain();
// Create the Snapshot
let best_hash = bc.best_block_hash();
let writer = Mutex::new(PackedWriter::new(&snapshot_path).unwrap());
let block_hashes = chunk_secondary(
Box::new(SNAPSHOT_MODE),
&bc,
best_hash,
&writer,
&Progress::default()
).unwrap();
let state_db = client.state_db().journal_db().boxed_clone();
let start_header = bc.block_header_data(&best_hash).unwrap();
let state_root = start_header.state_root();
let state_hashes = chunk_state(
state_db.as_hashdb(),
&state_root,
&writer,
&Progress::default(),
None
).unwrap();
let manifest = ::snapshot::ManifestData {
version: 2,
state_hashes: state_hashes,
state_root: state_root,
block_hashes: block_hashes,
block_number: NUM_BLOCKS,
block_hash: best_hash,
};
writer.into_inner().finish(manifest.clone()).unwrap();
// Initialize the Client
let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS);
let client_db = new_temp_db(&tempdir.path());
let client2 = Client::new(
ClientConfig::default(),
&spec,
client_db,
Arc::new(::miner::Miner::new_for_tests(&spec, None)),
IoChannel::disconnected(),
).unwrap();
// Add some ancient blocks
for block_number in 1..50 {
let block_hash = bc.block_hash(block_number).unwrap();
let block = bc.block(&block_hash).unwrap();
client2.import_block(Unverified::from_rlp(block.into_inner()).unwrap()).unwrap();
}
client2.import_verified_blocks();
client2.flush_queue();
// Restore the Snapshot
let reader = PackedReader::new(&snapshot_path).unwrap().unwrap();
let service_params = ServiceParams {
engine: spec.engine.clone(),
genesis_block: spec.genesis_block(),
restoration_db_handler: restoration_db_handler(db_config),
pruning: ::journaldb::Algorithm::Archive,
channel: IoChannel::disconnected(),
snapshot_root: tempdir.path().to_owned(),
client: client2.clone(),
};
let service = Service::new(service_params).unwrap();
service.init_restore(manifest.clone(), false).unwrap();
for hash in &manifest.block_hashes {
let chunk = reader.chunk(*hash).unwrap();
service.feed_block_chunk(*hash, &chunk);
}
for hash in &manifest.state_hashes {
let chunk = reader.chunk(*hash).unwrap();
service.feed_state_chunk(*hash, &chunk);
}
match service.status() {
RestorationStatus::Inactive => (),
RestorationStatus::Failed => panic!("Snapshot Restoration has failed."),
RestorationStatus::Ongoing { .. } => panic!("Snapshot Restoration should be done."),
_ => panic!("Invalid Snapshot Service status."),
}
// Check that the latest block number is the right one
assert_eq!(client2.block(BlockId::Latest).unwrap().number(), NUM_BLOCKS as u64);
// Check that we have blocks in [NUM_BLOCKS - NUM_SNAPSHOT_BLOCKS + 1 ; NUM_BLOCKS]
// but none before
assert!(client2.block(BlockId::Number(NUM_BLOCKS - NUM_SNAPSHOT_BLOCKS + 1)).is_some());
assert!(client2.block(BlockId::Number(100)).is_none());
// Check that the first 50 blocks have been migrated
for block_number in 1..49 {
assert!(client2.block(BlockId::Number(block_number)).is_some());
}
}
#[test]
fn recover_aborted_recovery() {
::env_logger::init().ok();
const NUM_BLOCKS: u32 = 400;
let gas_prices = vec![1.into(), 2.into(), 3.into(), 999.into()];
let client = generate_dummy_client_with_spec_and_data(Spec::new_null, NUM_BLOCKS, 5, &gas_prices);
let spec = Spec::new_null();
let tempdir = TempDir::new("").unwrap();
let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS);
let client_db = new_db();
let client2 = Client::new(
Default::default(),
&spec,
client_db,
Arc::new(::miner::Miner::new_for_tests(&spec, None)),
IoChannel::disconnected(),
).unwrap();
let service_params = ServiceParams {
engine: spec.engine.clone(),
genesis_block: spec.genesis_block(),
restoration_db_handler: restoration_db_handler(db_config),
pruning: ::journaldb::Algorithm::Archive,
channel: IoChannel::disconnected(),
snapshot_root: tempdir.path().to_owned(),
client: client2.clone(),
};
let service = Service::new(service_params).unwrap();
service.take_snapshot(&client, NUM_BLOCKS as u64).unwrap();
let manifest = service.manifest().unwrap();
service.init_restore(manifest.clone(), true).unwrap();
// Restore only the state chunks
for hash in &manifest.state_hashes {
let chunk = service.chunk(*hash).unwrap();
service.feed_state_chunk(*hash, &chunk);
}
match service.status() {
RestorationStatus::Ongoing { block_chunks_done, state_chunks_done, .. } => {
assert_eq!(state_chunks_done, manifest.state_hashes.len() as u32);
assert_eq!(block_chunks_done, 0);
},
e => panic!("Snapshot restoration must be ongoing ; {:?}", e),
}
// Abort the restore...
service.abort_restore();
// And try again!
service.init_restore(manifest.clone(), true).unwrap();
match service.status() {
RestorationStatus::Ongoing { block_chunks_done, state_chunks_done, .. } => {
assert_eq!(state_chunks_done, manifest.state_hashes.len() as u32);
assert_eq!(block_chunks_done, 0);
},
e => panic!("Snapshot restoration must be ongoing ; {:?}", e),
}
// Remove the snapshot directory, and restart the restoration
// It shouldn't have restored any previous blocks
fs::remove_dir_all(tempdir.path()).unwrap();
// And try again!
service.init_restore(manifest.clone(), true).unwrap();
match service.status() {
RestorationStatus::Ongoing { block_chunks_done, state_chunks_done, .. } => {
assert_eq!(block_chunks_done, 0);
assert_eq!(state_chunks_done, 0);
},
_ => panic!("Snapshot restoration must be ongoing"),
}
}

View File

@@ -213,7 +213,7 @@ impl Account {
/// Get (and cache) the contents of the trie's storage at `key`.
/// Takes modified storage into account.
pub fn storage_at(&self, db: &HashDB<KeccakHasher>, key: &H256) -> TrieResult<H256> {
pub fn storage_at(&self, db: &HashDB<KeccakHasher, DBValue>, key: &H256) -> TrieResult<H256> {
if let Some(value) = self.cached_storage_at(key) {
return Ok(value);
}
@@ -226,7 +226,7 @@ impl Account {
/// Get (and cache) the contents of the trie's storage at `key`.
/// Does not take modified storage into account.
pub fn original_storage_at(&self, db: &HashDB<KeccakHasher>, key: &H256) -> TrieResult<H256> {
pub fn original_storage_at(&self, db: &HashDB<KeccakHasher, DBValue>, key: &H256) -> TrieResult<H256> {
if let Some(value) = self.cached_original_storage_at(key) {
return Ok(value);
}
@@ -248,7 +248,7 @@ impl Account {
}
}
fn get_and_cache_storage(storage_root: &H256, storage_cache: &mut LruCache<H256, H256>, db: &HashDB<KeccakHasher>, key: &H256) -> TrieResult<H256> {
fn get_and_cache_storage(storage_root: &H256, storage_cache: &mut LruCache<H256, H256>, db: &HashDB<KeccakHasher, DBValue>, key: &H256) -> TrieResult<H256> {
let db = SecTrieDB::new(db, storage_root)?;
let panicky_decoder = |bytes:&[u8]| ::rlp::decode(&bytes).expect("decoding db value failed");
let item: U256 = db.get_with(key, panicky_decoder)?.unwrap_or_else(U256::zero);
@@ -354,7 +354,7 @@ impl Account {
/// Provide a database to get `code_hash`. Should not be called if it is a contract without code. Returns the cached code, if successful.
#[must_use]
pub fn cache_code(&mut self, db: &HashDB<KeccakHasher>) -> Option<Arc<Bytes>> {
pub fn cache_code(&mut self, db: &HashDB<KeccakHasher, DBValue>) -> Option<Arc<Bytes>> {
// TODO: fill out self.code_cache;
trace!("Account::cache_code: ic={}; self.code_hash={:?}, self.code_cache={}", self.is_cached(), self.code_hash, self.code_cache.pretty());
@@ -384,7 +384,7 @@ impl Account {
/// Provide a database to get `code_size`. Should not be called if it is a contract without code. Returns whether
/// the cache succeeds.
#[must_use]
pub fn cache_code_size(&mut self, db: &HashDB<KeccakHasher>) -> bool {
pub fn cache_code_size(&mut self, db: &HashDB<KeccakHasher, DBValue>) -> bool {
// TODO: fill out self.code_cache;
trace!("Account::cache_code_size: ic={}; self.code_hash={:?}, self.code_cache={}", self.is_cached(), self.code_hash, self.code_cache.pretty());
self.code_size.is_some() ||
@@ -473,7 +473,7 @@ impl Account {
}
/// Commit the `storage_changes` to the backing DB and update `storage_root`.
pub fn commit_storage(&mut self, trie_factory: &TrieFactory, db: &mut HashDB<KeccakHasher>) -> TrieResult<()> {
pub fn commit_storage(&mut self, trie_factory: &TrieFactory, db: &mut HashDB<KeccakHasher, DBValue>) -> TrieResult<()> {
let mut t = trie_factory.from_existing(db, &mut self.storage_root)?;
for (k, v) in self.storage_changes.drain() {
// cast key and value to trait type,
@@ -490,7 +490,7 @@ impl Account {
}
/// Commit any unsaved code. `code_hash` will always return the hash of the `code_cache` after this.
pub fn commit_code(&mut self, db: &mut HashDB<KeccakHasher>) {
pub fn commit_code(&mut self, db: &mut HashDB<KeccakHasher, DBValue>) {
trace!("Commiting code of {:?} - {:?}, {:?}", self, self.code_filth == Filth::Dirty, self.code_cache.is_empty());
match (self.code_filth == Filth::Dirty, self.code_cache.is_empty()) {
(true, true) => {
@@ -579,7 +579,7 @@ impl Account {
/// trie.
/// `storage_key` is the hash of the desired storage key, meaning
/// this will only work correctly under a secure trie.
pub fn prove_storage(&self, db: &HashDB<KeccakHasher>, storage_key: H256) -> TrieResult<(Vec<Bytes>, H256)> {
pub fn prove_storage(&self, db: &HashDB<KeccakHasher, DBValue>, storage_key: H256) -> TrieResult<(Vec<Bytes>, H256)> {
let mut recorder = Recorder::new();
let trie = TrieDB::new(db, &self.storage_root)?;

View File

@@ -28,16 +28,17 @@ use state::Account;
use parking_lot::Mutex;
use ethereum_types::{Address, H256};
use memorydb::MemoryDB;
use hashdb::{AsHashDB, HashDB, DBValue};
use hashdb::{AsHashDB, HashDB};
use kvdb::DBValue;
use keccak_hasher::KeccakHasher;
/// State backend. See module docs for more details.
pub trait Backend: Send {
/// Treat the backend as a read-only hashdb.
fn as_hashdb(&self) -> &HashDB<KeccakHasher>;
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue>;
/// Treat the backend as a writeable hashdb.
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher>;
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue>;
/// Add an account entry to the cache.
fn add_to_account_cache(&mut self, addr: Address, data: Option<Account>, modified: bool);
@@ -76,18 +77,18 @@ pub trait Backend: Send {
// TODO: when account lookup moved into backends, this won't rely as tenuously on intended
// usage.
#[derive(Clone, PartialEq)]
pub struct ProofCheck(MemoryDB<KeccakHasher>);
pub struct ProofCheck(MemoryDB<KeccakHasher, DBValue>);
impl ProofCheck {
/// Create a new `ProofCheck` backend from the given state items.
pub fn new(proof: &[DBValue]) -> Self {
let mut db = MemoryDB::<KeccakHasher>::new();
let mut db = MemoryDB::<KeccakHasher, DBValue>::new();
for item in proof { db.insert(item); }
ProofCheck(db)
}
}
impl HashDB<KeccakHasher> for ProofCheck {
impl HashDB<KeccakHasher, DBValue> for ProofCheck {
fn keys(&self) -> HashMap<H256, i32> { self.0.keys() }
fn get(&self, key: &H256) -> Option<DBValue> {
self.0.get(key)
@@ -108,14 +109,14 @@ impl HashDB<KeccakHasher> for ProofCheck {
fn remove(&mut self, _key: &H256) { }
}
impl AsHashDB<KeccakHasher> for ProofCheck {
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> { self }
impl AsHashDB<KeccakHasher, DBValue> for ProofCheck {
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> { self }
}
impl Backend for ProofCheck {
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> { self }
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> { self }
fn add_to_account_cache(&mut self, _addr: Address, _data: Option<Account>, _modified: bool) {}
fn cache_code(&self, _hash: H256, _code: Arc<Vec<u8>>) {}
fn get_cached_account(&self, _addr: &Address) -> Option<Option<Account>> { None }
@@ -134,18 +135,18 @@ impl Backend for ProofCheck {
/// The proof-of-execution can be extracted with `extract_proof`.
///
/// This doesn't cache anything or rely on the canonical state caches.
pub struct Proving<H: AsHashDB<KeccakHasher>> {
pub struct Proving<H: AsHashDB<KeccakHasher, DBValue>> {
base: H, // state we're proving values from.
changed: MemoryDB<KeccakHasher>, // changed state via insertions.
changed: MemoryDB<KeccakHasher, DBValue>, // changed state via insertions.
proof: Mutex<HashSet<DBValue>>,
}
impl<AH: AsHashDB<KeccakHasher> + Send + Sync> AsHashDB<KeccakHasher> for Proving<AH> {
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> { self }
impl<AH: AsHashDB<KeccakHasher, DBValue> + Send + Sync> AsHashDB<KeccakHasher, DBValue> for Proving<AH> {
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> { self }
}
impl<H: AsHashDB<KeccakHasher> + Send + Sync> HashDB<KeccakHasher> for Proving<H> {
impl<H: AsHashDB<KeccakHasher, DBValue> + Send + Sync> HashDB<KeccakHasher, DBValue> for Proving<H> {
fn keys(&self) -> HashMap<H256, i32> {
let mut keys = self.base.as_hashdb().keys();
keys.extend(self.changed.keys());
@@ -182,10 +183,10 @@ impl<H: AsHashDB<KeccakHasher> + Send + Sync> HashDB<KeccakHasher> for Proving<H
}
}
impl<H: AsHashDB<KeccakHasher> + Send + Sync> Backend for Proving<H> {
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self }
impl<H: AsHashDB<KeccakHasher, DBValue> + Send + Sync> Backend for Proving<H> {
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> { self }
fn add_to_account_cache(&mut self, _: Address, _: Option<Account>, _: bool) { }
@@ -204,13 +205,13 @@ impl<H: AsHashDB<KeccakHasher> + Send + Sync> Backend for Proving<H> {
fn is_known_null(&self, _: &Address) -> bool { false }
}
impl<H: AsHashDB<KeccakHasher>> Proving<H> {
impl<H: AsHashDB<KeccakHasher, DBValue>> Proving<H> {
/// Create a new `Proving` over a base database.
/// This will store all values ever fetched from that base.
pub fn new(base: H) -> Self {
Proving {
base: base,
changed: MemoryDB::<KeccakHasher>::new(),
changed: MemoryDB::<KeccakHasher, DBValue>::new(),
proof: Mutex::new(HashSet::new()),
}
}
@@ -222,7 +223,7 @@ impl<H: AsHashDB<KeccakHasher>> Proving<H> {
}
}
impl<H: AsHashDB<KeccakHasher> + Clone> Clone for Proving<H> {
impl<H: AsHashDB<KeccakHasher, DBValue> + Clone> Clone for Proving<H> {
fn clone(&self) -> Self {
Proving {
base: self.base.clone(),
@@ -236,12 +237,12 @@ impl<H: AsHashDB<KeccakHasher> + Clone> Clone for Proving<H> {
/// it. Doesn't cache anything.
pub struct Basic<H>(pub H);
impl<H: AsHashDB<KeccakHasher> + Send + Sync> Backend for Basic<H> {
fn as_hashdb(&self) -> &HashDB<KeccakHasher> {
impl<H: AsHashDB<KeccakHasher, DBValue> + Send + Sync> Backend for Basic<H> {
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> {
self.0.as_hashdb()
}
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> {
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> {
self.0.as_hashdb_mut()
}

View File

@@ -227,7 +227,7 @@ pub fn check_proof(
/// Prove a `virtual` transaction on the given state.
/// Returns `None` when the transacion could not be proved,
/// and a proof otherwise.
pub fn prove_transaction_virtual<H: AsHashDB<KeccakHasher> + Send + Sync>(
pub fn prove_transaction_virtual<H: AsHashDB<KeccakHasher, DBValue> + Send + Sync>(
db: H,
root: H256,
transaction: &SignedTransaction,
@@ -553,62 +553,70 @@ impl<B: Backend> State<B> {
}
/// Get the value of storage at a specific checkpoint.
pub fn checkpoint_storage_at(&self, checkpoint_index: usize, address: &Address, key: &H256) -> TrieResult<Option<H256>> {
pub fn checkpoint_storage_at(&self, start_checkpoint_index: usize, address: &Address, key: &H256) -> TrieResult<Option<H256>> {
#[must_use]
enum ReturnKind {
/// Use original storage at value at this address.
OriginalAt,
/// Use the downward checkpoint value.
Downward,
/// The checkpoint storage value is the same as the checkpoint storage value at the next checkpoint.
SameAsNext,
}
let (checkpoints_len, kind) = {
let kind = {
let checkpoints = self.checkpoints.borrow();
let checkpoints_len = checkpoints.len();
let checkpoint = match checkpoints.get(checkpoint_index) {
Some(checkpoint) => checkpoint,
if start_checkpoint_index >= checkpoints.len() {
// The checkpoint was not found. Return None.
None => return Ok(None),
};
return Ok(None);
}
let kind = match checkpoint.get(address) {
// The account exists at this checkpoint.
Some(Some(AccountEntry { account: Some(ref account), .. })) => {
if let Some(value) = account.cached_storage_at(key) {
return Ok(Some(value));
} else {
// This account has checkpoint entry, but the key is not in the entry's cache. We can use
// original_storage_at if current account's original storage root is the same as checkpoint
// account's original storage root. Otherwise, the account must be a newly created contract.
if account.base_storage_root() == self.original_storage_root(address)? {
ReturnKind::OriginalAt
let mut kind = None;
for checkpoint in checkpoints.iter().skip(start_checkpoint_index) {
match checkpoint.get(address) {
// The account exists at this checkpoint.
Some(Some(AccountEntry { account: Some(ref account), .. })) => {
if let Some(value) = account.cached_storage_at(key) {
return Ok(Some(value));
} else {
// If account base storage root is different from the original storage root since last
// commit, then it can only be created from a new contract, where the base storage root
// would always be empty. Note that this branch is actually never called, because
// `cached_storage_at` handled this case.
warn!("Trying to get an account's cached storage value, but base storage root does not equal to original storage root! Assuming the value is empty.");
return Ok(Some(H256::new()));
// This account has checkpoint entry, but the key is not in the entry's cache. We can use
// original_storage_at if current account's original storage root is the same as checkpoint
// account's original storage root. Otherwise, the account must be a newly created contract.
if account.base_storage_root() == self.original_storage_root(address)? {
kind = Some(ReturnKind::OriginalAt);
break
} else {
// If account base storage root is different from the original storage root since last
// commit, then it can only be created from a new contract, where the base storage root
// would always be empty. Note that this branch is actually never called, because
// `cached_storage_at` handled this case.
warn!(target: "state", "Trying to get an account's cached storage value, but base storage root does not equal to original storage root! Assuming the value is empty.");
return Ok(Some(H256::new()));
}
}
}
},
// The account didn't exist at that point. Return empty value.
Some(Some(AccountEntry { account: None, .. })) => return Ok(Some(H256::new())),
// The value was not cached at that checkpoint, meaning it was not modified at all.
Some(None) => ReturnKind::OriginalAt,
// This key does not have a checkpoint entry.
None => ReturnKind::Downward,
};
},
// The account didn't exist at that point. Return empty value.
Some(Some(AccountEntry { account: None, .. })) => return Ok(Some(H256::new())),
// The value was not cached at that checkpoint, meaning it was not modified at all.
Some(None) => {
kind = Some(ReturnKind::OriginalAt);
break
},
// This key does not have a checkpoint entry.
None => {
kind = Some(ReturnKind::SameAsNext);
},
}
}
(checkpoints_len, kind)
kind.expect("start_checkpoint_index is checked to be below checkpoints_len; for loop above must have been executed at least once; it will either early return, or set the kind value to Some; qed")
};
match kind {
ReturnKind::Downward => {
if checkpoint_index >= checkpoints_len - 1 {
Ok(Some(self.storage_at(address, key)?))
} else {
self.checkpoint_storage_at(checkpoint_index + 1, address, key)
}
ReturnKind::SameAsNext => {
// If we reached here, all previous SameAsNext failed to early return. It means that the value we want
// to fetch is the same as current.
Ok(Some(self.storage_at(address, key)?))
},
ReturnKind::OriginalAt => Ok(Some(self.original_storage_at(address, key)?)),
}
@@ -618,7 +626,7 @@ impl<B: Backend> State<B> {
&self, address: &Address, key: &H256, f_cached_at: FCachedStorageAt, f_at: FStorageAt,
) -> TrieResult<H256> where
FCachedStorageAt: Fn(&Account, &H256) -> Option<H256>,
FStorageAt: Fn(&Account, &HashDB<KeccakHasher>, &H256) -> TrieResult<H256>
FStorageAt: Fn(&Account, &HashDB<KeccakHasher, DBValue>, &H256) -> TrieResult<H256>
{
// Storage key search and update works like this:
// 1. If there's an entry for the account in the local cache check for the key and return it if found.
@@ -1014,7 +1022,7 @@ impl<B: Backend> State<B> {
/// Load required account data from the databases. Returns whether the cache succeeds.
#[must_use]
fn update_account_cache(require: RequireCache, account: &mut Account, state_db: &B, db: &HashDB<KeccakHasher>) -> bool {
fn update_account_cache(require: RequireCache, account: &mut Account, state_db: &B, db: &HashDB<KeccakHasher, DBValue>) -> bool {
if let RequireCache::None = require {
return true;
}
@@ -2471,6 +2479,33 @@ mod tests {
assert_eq!(orig_root, state.root().clone());
}
#[test]
fn create_contract_fail_previous_storage() {
let mut state = get_temp_state();
let a: Address = 1000.into();
let k = H256::from(U256::from(0));
state.set_storage(&a, k, H256::from(U256::from(0xffff))).unwrap();
state.commit().unwrap();
state.clear();
let orig_root = state.root().clone();
assert_eq!(state.storage_at(&a, &k).unwrap(), H256::from(U256::from(0xffff)));
state.clear();
state.checkpoint(); // c1
state.new_contract(&a, U256::zero(), U256::zero()).unwrap();
state.checkpoint(); // c2
state.set_storage(&a, k, H256::from(U256::from(2))).unwrap();
state.revert_to_checkpoint(); // revert to c2
assert_eq!(state.storage_at(&a, &k).unwrap(), H256::from(U256::from(0)));
state.revert_to_checkpoint(); // revert to c1
assert_eq!(state.storage_at(&a, &k).unwrap(), H256::from(U256::from(0xffff)));
state.commit().unwrap();
assert_eq!(orig_root, state.root().clone());
}
#[test]
fn create_empty() {
let mut state = get_temp_state();

View File

@@ -29,7 +29,7 @@ use hashdb::HashDB;
use keccak_hasher::KeccakHasher;
use header::BlockNumber;
use journaldb::JournalDB;
use kvdb::{KeyValueDB, DBTransaction};
use kvdb::{KeyValueDB, DBTransaction, DBValue};
use lru_cache::LruCache;
use memory_cache::MemoryLruCache;
use parking_lot::Mutex;
@@ -312,12 +312,12 @@ impl StateDB {
}
/// Conversion method to interpret self as `HashDB` reference
pub fn as_hashdb(&self) -> &HashDB<KeccakHasher> {
pub fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> {
self.db.as_hashdb()
}
/// Conversion method to interpret self as mutable `HashDB` reference
pub fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> {
pub fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> {
self.db.as_hashdb_mut()
}
@@ -412,9 +412,9 @@ impl StateDB {
}
impl state::Backend for StateDB {
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self.db.as_hashdb() }
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> { self.db.as_hashdb() }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> {
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> {
self.db.as_hashdb_mut()
}

View File

@@ -41,7 +41,7 @@ use transaction::{Action, Transaction, SignedTransaction};
use views::BlockView;
use blooms_db;
use kvdb::KeyValueDB;
use kvdb_rocksdb;
use kvdb_rocksdb::{self, Database, DatabaseConfig};
use tempdir::TempDir;
use verification::queue::kind::blocks::Unverified;
use encoded;
@@ -90,7 +90,7 @@ pub fn create_test_block_with_data(header: &Header, transactions: &[SignedTransa
rlp.append(header);
rlp.begin_list(transactions.len());
for t in transactions {
rlp.append_raw(&rlp::encode(t).into_vec(), 1);
rlp.append_raw(&rlp::encode(t), 1);
}
rlp.append_list(&uncles);
rlp.out()
@@ -263,30 +263,30 @@ pub fn get_test_client_with_blocks(blocks: Vec<Bytes>) -> Arc<Client> {
client
}
struct TestBlockChainDB {
_blooms_dir: TempDir,
_trace_blooms_dir: TempDir,
blooms: blooms_db::Database,
trace_blooms: blooms_db::Database,
key_value: Arc<KeyValueDB>,
}
impl BlockChainDB for TestBlockChainDB {
fn key_value(&self) -> &Arc<KeyValueDB> {
&self.key_value
}
fn blooms(&self) -> &blooms_db::Database {
&self.blooms
}
fn trace_blooms(&self) -> &blooms_db::Database {
&self.trace_blooms
}
}
/// Creates new test instance of `BlockChainDB`
pub fn new_db() -> Arc<BlockChainDB> {
struct TestBlockChainDB {
_blooms_dir: TempDir,
_trace_blooms_dir: TempDir,
blooms: blooms_db::Database,
trace_blooms: blooms_db::Database,
key_value: Arc<KeyValueDB>,
}
impl BlockChainDB for TestBlockChainDB {
fn key_value(&self) -> &Arc<KeyValueDB> {
&self.key_value
}
fn blooms(&self) -> &blooms_db::Database {
&self.blooms
}
fn trace_blooms(&self) -> &blooms_db::Database {
&self.trace_blooms
}
}
let blooms_dir = TempDir::new("").unwrap();
let trace_blooms_dir = TempDir::new("").unwrap();
@@ -301,6 +301,26 @@ pub fn new_db() -> Arc<BlockChainDB> {
Arc::new(db)
}
/// Creates a new temporary `BlockChainDB` on FS
pub fn new_temp_db(tempdir: &Path) -> Arc<BlockChainDB> {
let blooms_dir = TempDir::new("").unwrap();
let trace_blooms_dir = TempDir::new("").unwrap();
let key_value_dir = tempdir.join("key_value");
let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS);
let key_value_db = Database::open(&db_config, key_value_dir.to_str().unwrap()).unwrap();
let db = TestBlockChainDB {
blooms: blooms_db::Database::open(blooms_dir.path()).unwrap(),
trace_blooms: blooms_db::Database::open(trace_blooms_dir.path()).unwrap(),
_blooms_dir: blooms_dir,
_trace_blooms_dir: trace_blooms_dir,
key_value: Arc::new(key_value_db)
};
Arc::new(db)
}
/// Creates new instance of KeyValueDBHandler
pub fn restoration_db_handler(config: kvdb_rocksdb::DatabaseConfig) -> Box<BlockChainDBHandler> {
struct RestorationDBHandler {

View File

@@ -15,7 +15,7 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Trace database.
use std::collections::{HashMap, VecDeque};
use std::collections::HashMap;
use std::sync::Arc;
use blockchain::{BlockChainDB};
use heapsize::HeapSizeOf;
@@ -227,13 +227,12 @@ impl<T> TraceDatabase for TraceDB<T> where T: DatabaseExtras {
}
fn trace(&self, block_number: BlockNumber, tx_position: usize, trace_position: Vec<usize>) -> Option<LocalizedTrace> {
let trace_position_deq = VecDeque::from(trace_position);
self.extras.block_hash(block_number)
.and_then(|block_hash| self.transactions_traces(&block_hash)
.and_then(|traces| traces.into_iter().nth(tx_position))
.map(Into::<Vec<FlatTrace>>::into)
// this may and should be optimized
.and_then(|traces| traces.into_iter().find(|trace| trace.trace_address == trace_position_deq))
.and_then(|traces| traces.into_iter().find(|trace| trace.trace_address == trace_position))
.map(|trace| {
let tx_hash = self.extras.transaction_hash(block_number, tx_position)
.expect("Expected to find transaction hash. Database is probably corrupted");

View File

@@ -17,159 +17,175 @@
//! Simple executive tracer.
use ethereum_types::{U256, Address};
use vm::ActionParams;
use vm::{Error as VmError, ActionParams};
use trace::trace::{Call, Create, Action, Res, CreateResult, CallResult, VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, Suicide, Reward, RewardType};
use trace::{Tracer, VMTracer, FlatTrace, TraceError};
use trace::{Tracer, VMTracer, FlatTrace};
/// Simple executive tracer. Traces all calls and creates. Ignores delegatecalls.
#[derive(Default)]
pub struct ExecutiveTracer {
traces: Vec<FlatTrace>,
}
fn top_level_subtraces(traces: &[FlatTrace]) -> usize {
traces.iter().filter(|t| t.trace_address.is_empty()).count()
}
fn prefix_subtrace_addresses(mut traces: Vec<FlatTrace>) -> Vec<FlatTrace> {
// input traces are expected to be ordered like
// []
// [0]
// [0, 0]
// [0, 1]
// []
// [0]
//
// so they can be transformed to
//
// [0]
// [0, 0]
// [0, 0, 0]
// [0, 0, 1]
// [1]
// [1, 0]
let mut current_subtrace_index = 0;
let mut first = true;
for trace in &mut traces {
match (first, trace.trace_address.is_empty()) {
(true, _) => first = false,
(_, true) => current_subtrace_index += 1,
_ => {}
}
trace.trace_address.push_front(current_subtrace_index);
}
traces
}
#[test]
fn should_prefix_address_properly() {
use super::trace::{Action, Res, Suicide};
let f = |v: Vec<usize>| FlatTrace {
action: Action::Suicide(Suicide {
address: Default::default(),
balance: Default::default(),
refund_address: Default::default(),
}),
result: Res::None,
subtraces: 0,
trace_address: v.into_iter().collect(),
};
let t = vec![vec![], vec![0], vec![0, 0], vec![0], vec![], vec![], vec![0], vec![]].into_iter().map(&f).collect();
let t = prefix_subtrace_addresses(t);
assert_eq!(t, vec![vec![0], vec![0, 0], vec![0, 0, 0], vec![0, 0], vec![1], vec![2], vec![2, 0], vec![3]].into_iter().map(&f).collect::<Vec<_>>());
index_stack: Vec<usize>,
vecindex_stack: Vec<usize>,
sublen_stack: Vec<usize>,
skip_one: bool,
}
impl Tracer for ExecutiveTracer {
type Output = FlatTrace;
fn prepare_trace_call(&self, params: &ActionParams) -> Option<Call> {
Some(Call::from(params.clone()))
}
fn prepare_trace_call(&mut self, params: &ActionParams, depth: usize, is_builtin: bool) {
assert!(!self.skip_one, "skip_one is used only for builtin contracts that do not have subsequent calls; in prepare_trace_call it cannot be true; qed");
fn prepare_trace_create(&self, params: &ActionParams) -> Option<Create> {
Some(Create::from(params.clone()))
}
if depth != 0 && is_builtin && params.value.value() == U256::zero() {
self.skip_one = true;
return;
}
if let Some(parentlen) = self.sublen_stack.last_mut() {
*parentlen += 1;
}
fn trace_call(&mut self, call: Option<Call>, gas_used: U256, output: &[u8], subs: Vec<FlatTrace>) {
let trace = FlatTrace {
trace_address: Default::default(),
subtraces: top_level_subtraces(&subs),
action: Action::Call(call.expect("self.prepare_trace_call().is_some(): so we must be tracing: qed")),
trace_address: self.index_stack.clone(),
subtraces: self.sublen_stack.last().cloned().unwrap_or(0),
action: Action::Call(Call::from(params.clone())),
result: Res::Call(CallResult {
gas_used: gas_used,
output: output.into()
gas_used: U256::zero(),
output: Vec::new()
}),
};
debug!(target: "trace", "Traced call {:?}", trace);
self.vecindex_stack.push(self.traces.len());
self.traces.push(trace);
self.traces.extend(prefix_subtrace_addresses(subs));
self.index_stack.push(0);
self.sublen_stack.push(0);
}
fn trace_create(&mut self, create: Option<Create>, gas_used: U256, code: &[u8], address: Address, subs: Vec<FlatTrace>) {
fn prepare_trace_create(&mut self, params: &ActionParams) {
assert!(!self.skip_one, "skip_one is used only for builtin contracts that do not have subsequent calls; in prepare_trace_create it cannot be true; qed");
if let Some(parentlen) = self.sublen_stack.last_mut() {
*parentlen += 1;
}
let trace = FlatTrace {
subtraces: top_level_subtraces(&subs),
action: Action::Create(create.expect("self.prepare_trace_create().is_some(): so we must be tracing: qed")),
trace_address: self.index_stack.clone(),
subtraces: self.sublen_stack.last().cloned().unwrap_or(0),
action: Action::Create(Create::from(params.clone())),
result: Res::Create(CreateResult {
gas_used: gas_used,
code: code.into(),
address: address
gas_used: U256::zero(),
code: Vec::new(),
address: Address::default(),
}),
trace_address: Default::default(),
};
debug!(target: "trace", "Traced create {:?}", trace);
self.vecindex_stack.push(self.traces.len());
self.traces.push(trace);
self.traces.extend(prefix_subtrace_addresses(subs));
self.index_stack.push(0);
self.sublen_stack.push(0);
}
fn trace_failed_call(&mut self, call: Option<Call>, subs: Vec<FlatTrace>, error: TraceError) {
let trace = FlatTrace {
trace_address: Default::default(),
subtraces: top_level_subtraces(&subs),
action: Action::Call(call.expect("self.prepare_trace_call().is_some(): so we must be tracing: qed")),
result: Res::FailedCall(error),
};
debug!(target: "trace", "Traced failed call {:?}", trace);
self.traces.push(trace);
self.traces.extend(prefix_subtrace_addresses(subs));
fn done_trace_call(&mut self, gas_used: U256, output: &[u8]) {
if self.skip_one {
self.skip_one = false;
return;
}
let vecindex = self.vecindex_stack.pop().expect("Executive invoked prepare_trace_call before this function; vecindex_stack is never empty; qed");
let sublen = self.sublen_stack.pop().expect("Executive invoked prepare_trace_call before this function; sublen_stack is never empty; qed");
self.index_stack.pop();
self.traces[vecindex].result = Res::Call(CallResult {
gas_used,
output: output.into(),
});
self.traces[vecindex].subtraces = sublen;
if let Some(index) = self.index_stack.last_mut() {
*index += 1;
}
}
fn trace_failed_create(&mut self, create: Option<Create>, subs: Vec<FlatTrace>, error: TraceError) {
let trace = FlatTrace {
subtraces: top_level_subtraces(&subs),
action: Action::Create(create.expect("self.prepare_trace_create().is_some(): so we must be tracing: qed")),
result: Res::FailedCreate(error),
trace_address: Default::default(),
fn done_trace_create(&mut self, gas_used: U256, code: &[u8], address: Address) {
assert!(!self.skip_one, "skip_one is only set with prepare_trace_call for builtin contracts with no subsequent calls; skip_one cannot be true after the same level prepare_trace_create; qed");
let vecindex = self.vecindex_stack.pop().expect("Executive invoked prepare_trace_create before this function; vecindex_stack is never empty; qed");
let sublen = self.sublen_stack.pop().expect("Executive invoked prepare_trace_create before this function; sublen_stack is never empty; qed");
self.index_stack.pop();
self.traces[vecindex].result = Res::Create(CreateResult {
gas_used, address,
code: code.into(),
});
self.traces[vecindex].subtraces = sublen;
if let Some(index) = self.index_stack.last_mut() {
*index += 1;
}
}
fn done_trace_failed(&mut self, error: &VmError) {
if self.skip_one {
self.skip_one = false;
return;
}
let vecindex = self.vecindex_stack.pop().expect("Executive invoked prepare_trace_create/call before this function; vecindex_stack is never empty; qed");
let sublen = self.sublen_stack.pop().expect("Executive invoked prepare_trace_create/call before this function; vecindex_stack is never empty; qed");
self.index_stack.pop();
let is_create = match self.traces[vecindex].action {
Action::Create(_) => true,
_ => false,
};
debug!(target: "trace", "Traced failed create {:?}", trace);
self.traces.push(trace);
self.traces.extend(prefix_subtrace_addresses(subs));
if is_create {
self.traces[vecindex].result = Res::FailedCreate(error.into());
} else {
self.traces[vecindex].result = Res::FailedCall(error.into());
}
self.traces[vecindex].subtraces = sublen;
if let Some(index) = self.index_stack.last_mut() {
*index += 1;
}
}
fn trace_suicide(&mut self, address: Address, balance: U256, refund_address: Address) {
if let Some(parentlen) = self.sublen_stack.last_mut() {
*parentlen += 1;
}
let trace = FlatTrace {
subtraces: 0,
action: Action::Suicide(Suicide { address, refund_address, balance } ),
result: Res::None,
trace_address: Default::default(),
trace_address: self.index_stack.clone(),
};
debug!(target: "trace", "Traced suicide {:?}", trace);
self.traces.push(trace);
if let Some(index) = self.index_stack.last_mut() {
*index += 1;
}
}
fn trace_reward(&mut self, author: Address, value: U256, reward_type: RewardType) {
if let Some(parentlen) = self.sublen_stack.last_mut() {
*parentlen += 1;
}
let trace = FlatTrace {
subtraces: 0,
action: Action::Reward(Reward { author, value, reward_type } ),
result: Res::None,
trace_address: Default::default(),
trace_address: self.index_stack.clone(),
};
debug!(target: "trace", "Traced reward {:?}", trace);
self.traces.push(trace);
}
fn subtracer(&self) -> Self {
ExecutiveTracer::default()
if let Some(index) = self.index_stack.last_mut() {
*index += 1;
}
}
fn drain(self) -> Vec<FlatTrace> {
@@ -180,6 +196,9 @@ impl Tracer for ExecutiveTracer {
/// Simple VM tracer. Traces all operations.
pub struct ExecutiveVMTracer {
data: VMTrace,
depth: usize,
last_mem_written: Option<(usize, usize)>,
last_store_written: Option<(U256, U256)>,
}
impl ExecutiveVMTracer {
@@ -191,7 +210,18 @@ impl ExecutiveVMTracer {
code: vec![],
operations: vec![Default::default()], // prefill with a single entry so that prepare_subtrace can get the parent_step
subs: vec![],
}
},
depth: 0,
last_mem_written: None,
last_store_written: None,
}
}
fn with_trace_in_depth<F: Fn(&mut VMTrace)>(trace: &mut VMTrace, depth: usize, f: F) {
if depth == 0 {
f(trace);
} else {
Self::with_trace_in_depth(trace.subs.last_mut().expect("self.depth is incremented with prepare_subtrace; a subtrace is always pushed; self.depth cannot be greater than subtrace stack; qed"), depth - 1, f);
}
}
}
@@ -201,37 +231,77 @@ impl VMTracer for ExecutiveVMTracer {
fn trace_next_instruction(&mut self, _pc: usize, _instruction: u8, _current_gas: U256) -> bool { true }
fn trace_prepare_execute(&mut self, pc: usize, instruction: u8, gas_cost: U256) {
self.data.operations.push(VMOperation {
pc: pc,
instruction: instruction,
gas_cost: gas_cost,
executed: None,
fn trace_prepare_execute(&mut self, pc: usize, instruction: u8, gas_cost: U256, mem_written: Option<(usize, usize)>, store_written: Option<(U256, U256)>) {
Self::with_trace_in_depth(&mut self.data, self.depth, move |trace| {
trace.operations.push(VMOperation {
pc: pc,
instruction: instruction,
gas_cost: gas_cost,
executed: None,
});
});
self.last_mem_written = mem_written;
self.last_store_written = store_written;
}
fn trace_executed(&mut self, gas_used: U256, stack_push: &[U256], mem: &[u8]) {
let mem_diff = self.last_mem_written.take().map(|(o, s)| (o, &(mem[o..o+s])));
let store_diff = self.last_store_written.take();
Self::with_trace_in_depth(&mut self.data, self.depth, move |trace| {
let ex = VMExecutedOperation {
gas_used: gas_used,
stack_push: stack_push.iter().cloned().collect(),
mem_diff: mem_diff.map(|(s, r)| MemoryDiff { offset: s, data: r.iter().cloned().collect() }),
store_diff: store_diff.map(|(l, v)| StorageDiff { location: l, value: v }),
};
trace.operations.last_mut().expect("trace_executed is always called after a trace_prepare_execute; trace.operations cannot be empty; qed").executed = Some(ex);
});
}
fn trace_executed(&mut self, gas_used: U256, stack_push: &[U256], mem_diff: Option<(usize, &[u8])>, store_diff: Option<(U256, U256)>) {
let ex = VMExecutedOperation {
gas_used: gas_used,
stack_push: stack_push.iter().cloned().collect(),
mem_diff: mem_diff.map(|(s, r)| MemoryDiff{ offset: s, data: r.iter().cloned().collect() }),
store_diff: store_diff.map(|(l, v)| StorageDiff{ location: l, value: v }),
};
self.data.operations.last_mut().expect("trace_executed is always called after a trace_prepare_execute").executed = Some(ex);
fn prepare_subtrace(&mut self, code: &[u8]) {
Self::with_trace_in_depth(&mut self.data, self.depth, move |trace| {
let parent_step = trace.operations.len() - 1; // won't overflow since we must already have pushed an operation in trace_prepare_execute.
trace.subs.push(VMTrace {
parent_step,
code: code.to_vec(),
operations: vec![],
subs: vec![],
});
});
self.depth += 1;
}
fn prepare_subtrace(&self, code: &[u8]) -> Self {
ExecutiveVMTracer { data: VMTrace {
parent_step: self.data.operations.len() - 1, // won't overflow since we must already have pushed an operation in trace_prepare_execute.
code: code.to_vec(),
operations: vec![],
subs: vec![],
}}
}
fn done_subtrace(&mut self, sub: Self) {
self.data.subs.push(sub.data);
fn done_subtrace(&mut self) {
self.depth -= 1;
}
fn drain(mut self) -> Option<VMTrace> { self.data.subs.pop() }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn should_prefix_address_properly() {
let mut tracer = ExecutiveTracer::default();
tracer.prepare_trace_call(&ActionParams::default(), 0, false);
tracer.prepare_trace_call(&ActionParams::default(), 1, false);
tracer.prepare_trace_call(&ActionParams::default(), 2, false);
tracer.done_trace_call(U256::zero(), &[]);
tracer.prepare_trace_call(&ActionParams::default(), 2, false);
tracer.done_trace_call(U256::zero(), &[]);
tracer.prepare_trace_call(&ActionParams::default(), 2, false);
tracer.done_trace_call(U256::zero(), &[]);
tracer.done_trace_call(U256::zero(), &[]);
tracer.done_trace_call(U256::zero(), &[]);
let drained = tracer.drain();
assert!(drained[0].trace_address.len() == 0);
assert_eq!(&drained[1].trace_address, &[0]);
assert_eq!(&drained[2].trace_address, &[0, 0]);
assert_eq!(&drained[3].trace_address, &[0, 1]);
assert_eq!(&drained[4].trace_address, &[0, 2]);
}
}

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