Compare commits

..

19 Commits

Author SHA1 Message Date
André Silva
39b9f1e252 [stable] Backports (#8623)
* Fix account list double 0x display (#8596)

* Remove unused self import

* Fix account list double 0x display

* Trace precompiled contracts when the transfer value is not zero (#8486)

* Trace precompiled contracts when the transfer value is not zero

* Add tests for precompiled CALL tracing

* Use byzantium test machine for the new test

* Add notes in comments on why we don't trace all precompileds

* Use is_transferred instead of transferred

* Gitlab test script fixes (#8573)

* Exclude /docs from modified files.

* Ensure all references in the working tree are available

* Remove duplicated line from test script
2018-05-14 15:52:51 +02:00
Afri Schoedon
226a1d31b6 Bump stable to 1.10.4 (#8626) 2018-05-14 15:52:18 +02:00
Afri Schoedon
063b0761f5 Allow stable snaps to be stable. (#8582) 2018-05-14 04:21:48 -05:00
Tomasz Drwięga
b9ceda38a6 [stable] Backports (#8557)
* Update wasmi and pwasm-utils (#8493)

* Update wasmi to 0.2

New wasmi supports 32bit platforms and no longer requires a special feature to build for such platforms.

* Update pwasm-utils to 0.1.5

* Fetching logs by hash in blockchain database (#8463)

* Fetch logs by hash in blockchain database

* Fix tests

* Add unit test for branch block logs fetching

* Add docs that blocks must already be sorted

* Handle branch block cases properly

* typo: empty -> is_empty

* Remove return_empty_if_none by using a closure

* Use BTreeSet to avoid sorting again

* Move is_canon to BlockChain

* typo: pass value by reference

* Use loop and wrap inside blocks to simplify the code

Borrowed from https://github.com/paritytech/parity/pull/8463#discussion_r183453326

* typo: missed a comment

* Pass on storage keys tracing to handle the case when it is not modified (#8491)

* Pass on storage keys even if it is not modified

* typo: account and storage query

`to_pod_diff` builds both `touched_addresses` merge and storage keys merge.

* Fix tests

* Use state query directly because of suicided accounts

* Fix a RefCell borrow issue

* Add tests for unmodified storage trace

* Address grumbles

* typo: remove unwanted empty line

* ensure_cached compiles with the original signature

* Enable WebAssembly and Byzantium for Ellaism (#8520)

* Enable WebAssembly and Byzantium for Ellaism

* Fix indentation

* Remove empty lines

* Fix compilation.
2018-05-07 20:17:28 +02:00
Afri Schoedon
d9f6aba308 Stabilize 1.10.3 (#8474)
* Stabelize 1.10

* Bump stable to 1.10.3

* Update Gitlab scripts

* Fix snap builds (#8483)

* fix docker build (#8462)

* Use  as Docker's  ( is not used anymore)
2018-04-27 17:45:45 +02:00
Afri Schoedon
f4ae813fda Update Parity beta to 1.10.2 + Backports (#8455)
* Update Parity beta to 1.10.2

* Allow 32 bit pipelines to fail (#8454)

* Disable 32bit tragets for gitlab

* Rename linux pipelines

* Update wasmi (#8452)

* Fix Cargo.lock

* Revert Cargo.lock changes

* Revert Cargo.lock changes

* Fix Cargo.lock
2018-04-23 10:31:05 +02:00
Wei Tang
7202f7ae82 [beta] Backports (#8450)
* Use forked app_dirs crate for reverted Windows dir behavior  (#8438)

* Remove unused appdirs dependency in CLI

* Use forked app_dirs crate for reverted Windows dir behavior

* remove Tendermint extra_info due to seal inconsistencies (#8367)

* handle queue import errors a bit more gracefully (#8385)

* Improve VM executor stack size estimation rules (#8439)

* Improve VM executor stack size estimation rules

* typo: docs add "(Debug build)" comment

* Fix an off by one typo and set minimal stack size

This avoids the case if `depth_threshold == max_depth`. Usually setting stack size to zero will just rebound it to
platform minimal stack size, but we set it here just in case.

* Use saturating_sub to avoid potential overflow
2018-04-20 15:22:29 +02:00
Afri Schoedon
45c29a2a57 Bump beta to 1.10.1 (#8350)
* Bump beta to 1.10.1

* Unflag critical release
2018-04-13 14:39:38 +02:00
Tomasz Drwięga
fc652db729 [beta] Backports (#8346)
* Warp-only sync with warp-barrier [blocknumber] flag. (#8228)

* Warp-only sync with warp-after [blocknumber] flag.

* Fix tests.

* Fix configuration tests.

* Rename to warp barrier.

* Allow unsafe js eval on Parity Wallet. (#8204)

* Update musicoin spec in line with gmc v2.6.2 (#8242)

* Supress TemporaryInvalid verification failures. (#8256)

* Include suicided accounts in state diff (#8297)

* Include suicided accounts in state diff

* Shorten form match -> if let

* Test suicide trace diff in State

* replace_home for password_files, reserved_peers and log_file (#8324)

* replace_home for password_files, reserved_peers and log_file

* typo: arg_log_file is Option

* Enable UI by default, but only display info page.

* Fix test.

* Fix naming and remove old todo.

* Change "wallet" with "browser UI"
2018-04-10 12:16:08 +02:00
Amaury Martiny
68320e8e89 Change name Wallet -> UI (#8164) (#8205)
* Change name Wallet -> UI

* Make warning bold
2018-04-04 18:07:36 +02:00
Marek Kotewicz
fdd03cc40d Backport #8099 (#8132) 2018-04-04 21:33:14 +09:00
Nikolay Volf
c3d446420c Beta backprots (WASM libs) (#8220)
* bump wasm libs (#8171)

* bump wasmi version (#8209)
2018-03-26 15:29:16 +02:00
Toralf Wittner
9e7f887606 Update hyper to 0.11.24 (#8203) 2018-03-24 14:34:22 +09:00
Kirill Pimenov
5acdd091a2 Updated jsonrpc to include latest backports (beta) (#8181)
* Updated jsonrpc to include latest backports

* Update dependencies.

- `jsonrpc` PR #244 required `hyper >= 0.11.20` which in turn required
updating `tokio-core`, `mio` and `iovec`.

- `jsonrpc` PR #246 required updating `https://github.com/tomusdrw/ws-rs`.
2018-03-23 14:32:42 +01:00
André Silva
0a9d41e294 Re-enable signer, even with no UI. (#8167) (#8168)
* Re-enable signer, even with no UI.

* Fix message.
2018-03-20 22:49:07 +01:00
André Silva
610f6f1425 [Beta] Backports (#8136)
* Support parity protocol. (#8035)

* updater: apply exponential backoff after download failure (#8059)

* updater: apply exponential backoff after download failure

* updater: reset backoff on new release

* Max code size on Kovan (#8067)

* Enable code size limit on kovan

* Fix formatting.

* Limit incoming connections.  (#8060)

* Limit ingress connections
* Optimized handshakes logging

* WASM libraries bump (#7970)

* update wasmi, parity-wasm, wasm-utils to latest version

* Update to new wasmi & error handling

* also utilize new stack limiter

* fix typo

* replace dependency url

* Cargo.lock update

* add some dos protection (#8084)

* revert removing blooms (#8066)

* Revert "fix traces, removed bloomchain crate, closes #7228, closes #7167"

This reverts commit 1bf62038678295e5586f02a38a0c5aab9a9efe62.

* Revert "fixed broken logs (#7934)"

This reverts commit f8a2e53f3e.

* fixed broken logs

* bring back old lock order

* remove migration v13

* revert CURRENT_VERSION to 12 in migration.rs

* more dos protection (#8104)

* Const time comparison (#8113)

* Use `subtle::slices_equal` for constant time comparison.

Also update the existing version of subtle in `ethcrypto` from
0.1 to 0.5

* Test specifically for InvalidPassword error.

* fix trace filter returning returning unrelated reward calls, closes #8070 (#8098)

* network: init discovery using healthy nodes (#8061)

* network: init discovery using healthy nodes

* network: fix style grumble

* network: fix typo

* Postpone Kovan hard fork (#8137)

* ethcore: postpone Kovan hard fork

* util: update version fork metadata

* Disable UI by default. (#8105)

* dapps: update parity-ui dependencies (#8160)
2018-03-19 21:40:56 +01:00
Kirill Pimenov
2403fc52c1 Probe changes one step deeper (#8134) (#8135) 2018-03-19 03:23:18 +01:00
Rando
0ab1930c04 Beta backports (#8053)
* CI: Fix cargo cache (#7968)

* Fix cache

Blocking waiting for file lock on the registry index

* Only clean locked cargo cache on windows

* fixed ethstore sign (#8026)

* fixed parsing ethash seals and verify_block_undordered (#8031)

* fix for verify_block_basic crashing on invalid transaction rlp (#8032)

* fix cache & snapcraft CI build (#8052)

after successful testing it is necessary to port in a ```beta``` and ```stable```

*  Add MCIP-6 Byzyantium transition to Musicoin spec (#7841)

* Add test chain spec for musicoin byzantium testnet

* Add MCIP-6 Byzyantium transition to Musicoin spec

* Update mcip6_byz.json

* ethcore: update musicoin byzantium block number

* ethcore: update musicoin byzantium block number

* ethcore: update musicoin bootnodes

* Update musicoin.json

* Update musicoin.json

* More bootnodes.
2018-03-14 12:31:31 +01:00
Rando
3d6ede0c58 Make 1.10 beta (#8022)
* Make 1.10 beta

* Fix gitlab builds
2018-03-01 21:18:26 +03:00
554 changed files with 19199 additions and 46366 deletions

View File

@@ -180,30 +180,10 @@ windows:
paths:
- parity.zip
name: "x86_64-pc-windows-msvc_parity"
android-armv7:
stage: build
image: parity/parity-android:latest
only:
- beta
- tags
- stable
- triggers
script:
- cargo build --target=armv7-linux-androideabi
tags:
- rust-arm
allow_failure: true
artifacts:
paths:
- parity.zip
name: "armv7-linux-androideabi_parity"
docker-build:
stage: build
only:
- tags
- master
- beta
- stable
- triggers
before_script:
- docker info

View File

@@ -1,273 +1,386 @@
## Parity [v1.10.2](https://github.com/paritytech/parity/releases/tag/v1.10.2) (2018-04-24)
## Parity [v1.9.3](https://github.com/paritytech/parity/releases/tag/v1.9.3) (2018-02-20)
Parity 1.10.2 is a bug-fix release to improve performance and stability.
Parity 1.9.3 is a bug-fix release to improve performance and stability.
The full list of included changes:
- Update Parity beta to 1.10.2 + Backports ([#8455](https://github.com/paritytech/parity/pull/8455))
- Update Parity beta to 1.10.2
- Allow 32-bit pipelines to fail ([#8454](https://github.com/paritytech/parity/pull/8454))
- Disable 32-bit targets for Gitlab
- Rename Linux pipelines
- Update wasmi ([#8452](https://github.com/paritytech/parity/pull/8452))
- Fix Cargo.lock
- Backports ([#8450](https://github.com/paritytech/parity/pull/8450))
- Use forked app_dirs crate for reverted Windows dir behavior ([#8438](https://github.com/paritytech/parity/pull/8438))
- Remove unused app_dirs dependency in CLI
- Use forked app_dirs crate for reverted Windows dir behavior
- Remove Tendermint extra_info due to seal inconsistencies ([#8367](https://github.com/paritytech/parity/pull/8367))
- Handle queue import errors a bit more gracefully ([#8385](https://github.com/paritytech/parity/pull/8385))
- Improve VM executor stack size estimation rules ([#8439](https://github.com/paritytech/parity/pull/8439))
- Improve VM executor stack size estimation rules
- Typo: docs add "(Debug build)" comment
- Fix an off by one typo and set minimal stack size
- Use saturating_sub to avoid potential overflow
- Backports ([#7945](https://github.com/paritytech/parity/pull/7945))
- ECIP 1041 - Remove Difficulty Bomb ([#7905](https://github.com/paritytech/parity/pull/7905))
- spec: Validate required divisor fields are not 0 ([#7933](https://github.com/paritytech/parity/pull/7933))
- Kovan WASM fork code ([#7849](https://github.com/paritytech/parity/pull/7849))
- Gitlab Cargo Cache ([#7944](https://github.com/paritytech/parity/pull/7944))
- Bump react-qr-reader ([#7943](https://github.com/paritytech/parity/pull/7943))
- Update react-qr-reader
- Explicit webrtc-adapter dependency (package-lock workaround)
- Iframe with allow (QR, new Chrome policy)
- Backport of [#7844](https://github.com/paritytech/parity/pull/7844) and [#7917](https://github.com/paritytech/parity/pull/7917) to beta ([#7940](https://github.com/paritytech/parity/pull/7940))
- Randomize the peer we dispatch to
- Fix a division by zero in light client RPC handler
- Wallet allowJsEval: true ([#7913](https://github.com/paritytech/parity/pull/7913))
- Wallet allowJsEval: true
- Fix unsafe wallet.
- Enable unsafe-eval for all dapps.
- Fix CSP for dapps that require eval. ([#7867](https://github.com/paritytech/parity/pull/7867)) ([#7903](https://github.com/paritytech/parity/pull/7903))
- Add allowJsEval to manifest.
- Enable 'unsafe-eval' if requested in manifest.
- Fix snap build beta ([#7895](https://github.com/paritytech/parity/pull/7895))
- Fix snapcraft grade to stable ([#7894](https://github.com/paritytech/parity/pull/7894))
- Backport Master CI PRs to Beta ([#7890](https://github.com/paritytech/parity/pull/7890))
- Add binary identifiers and sha256sum to builds ([#7830](https://github.com/paritytech/parity/pull/7830))
- Fix checksums and auto-update push ([#7846](https://github.com/paritytech/parity/pull/7846))
- Update gitlab-build.sh ([#7855](https://github.com/paritytech/parity/pull/7855))
- Fix installer binary names for macos and windows ([#7881](https://github.com/paritytech/parity/pull/7881))
- Update gitlab-test.sh ([#7883](https://github.com/paritytech/parity/pull/7883))
- Fix snapcraft nightly ([#7884](https://github.com/paritytech/parity/pull/7884))
- Backport Core PRs to beta ([#7891](https://github.com/paritytech/parity/pull/7891))
- Update back-references more aggressively after answering from cache ([#7578](https://github.com/paritytech/parity/pull/7578))
- Updated WASM Runtime & new interpreter (wasmi) ([#7796](https://github.com/paritytech/parity/pull/7796))
- Adjust storage update evm-style ([#7812](https://github.com/paritytech/parity/pull/7812))
- Add new EF ropstens nodes ([#7824](https://github.com/paritytech/parity/pull/7824))
- Store updater metadata in a single place ([#7832](https://github.com/paritytech/parity/pull/7832))
- WASM: Disable internal memory ([#7842](https://github.com/paritytech/parity/pull/7842))
- Add a timeout for light client sync requests ([#7848](https://github.com/paritytech/parity/pull/7848))
- Flush keyfiles. Resolves [#7632](https://github.com/paritytech/parity/issues/7632) ([#7868](https://github.com/paritytech/parity/pull/7868))
- Fix wallet import ([#7873](https://github.com/paritytech/parity/pull/7873))
## Parity [v1.10.1](https://github.com/paritytech/parity/releases/tag/v1.10.1) (2018-04-17)
## Parity [v1.9.2](https://github.com/paritytech/parity/releases/tag/v1.9.2) (2018-02-02)
Parity 1.10.1 is a bug-fix release to improve performance and stability. Among other changes, you can now use `--warp-barrier [BLOCK]` to specify a minimum block number to `--warp` to. This is useful in cases where clients restore to outdated snapshots far behind the latest chain head.
Parity 1.9.2 is a bug-fix release to improve performance and stability. It adds additional bootnodes for the Ropsten test network.
The full list of included changes:
- Bump beta to 1.10.1 ([#8350](https://github.com/paritytech/parity/pull/8350))
- Bump beta to 1.10.1
- Unflag critical release
- Backports ([#8346](https://github.com/paritytech/parity/pull/8346))
- Warp-only sync with warp-barrier [blocknumber] flag. ([#8228](https://github.com/paritytech/parity/pull/8228))
- Warp-only sync with warp-after [blocknumber] flag.
- Backports beta ([#7780](https://github.com/paritytech/parity/pull/7780))
- Bump beta to 1.9.2
- Update ropsten.json ([#7776](https://github.com/paritytech/parity/pull/7776))
- Snapcraft push beta
## Parity [v1.9.1](https://github.com/paritytech/parity/releases/tag/v1.9.1) (2018-02-01)
Parity 1.9.1 is a bug-fix release to improve performance and stability. It restores ERC-20 token balances, improves networking, fixes database corruptions on client shutdown, and fixes issues with the `--password` command-line flag. Happy syncing, fellow Ethereans!
In addition, this stabilizes Kovan and other Proof-of-Authority networks. If you run a network with AuRa engine, updating is highly encouraged!
The full list of included changes:
- Beta Backports ([#7756](https://github.com/paritytech/parity/pull/7756))
- Filter-out nodes.json ([#7716](https://github.com/paritytech/parity/pull/7716))
- Filter-out nodes.json
- network: sort node table nodes by failure ratio
- network: fix node table tests
- network: fit node failure percentage into buckets of 5%
- network: consider number of attempts in sorting of node table
- network: fix node table grumbles
- Fix client not being dropped on shutdown ([#7695](https://github.com/paritytech/parity/pull/7695))
- parity: wait for client to drop on shutdown
- parity: fix grumbles in shutdown wait
- parity: increase shutdown timeouts
- Wrap --help output to 120 characters ([#7626](https://github.com/paritytech/parity/pull/7626))
- Update Clap dependency and remove workarounds
- WIP
- Remove line breaks in help messages for now
- Multiple values can only be separated by commas (closes [#7428](https://github.com/paritytech/parity/issues/7428))
- Grumbles; refactor repeating code; add constant
- Use a single Wrapper rather than allocate a new one for each call
- Wrap --help to 120 characters rather than 100 characte
- Token filter balances (throttle) ([#7742](https://github.com/paritytech/parity/pull/7742))
- Token filter balances (throttle)
- Cleanups
- Remove unused uniq
- Update @parity/shared to 2.2.23
- Remove unused code paths
- Bump beta to 1.9.1 ([#7751](https://github.com/paritytech/parity/pull/7751))
- Explicitly add branch name ([#7754](https://github.com/paritytech/parity/pull/7754))
- Explicitly add branch name
- Fix cargo update branch to beta
- Revert revert revert ([#7715](https://github.com/paritytech/parity/pull/7715))
- This reverts commit 568dc33.
## Parity [v1.9.0](https://github.com/paritytech/parity/releases/tag/v1.9.0) "Velocity" (2018-01-25)
We are happy to announce our newest Parity 1.9 release. Among others, it enables the following features:
- It integrates the fully reworked Parity Wallet and DApps browser (a.k.a. "UI 2.0", [#6819](https://github.com/paritytech/parity/pull/6819)).
- It enables devp2p snappy compression ([#6683](https://github.com/paritytech/parity/pull/6683)).
- AuRa Proof-of-Authority chains now disable uncles by default ([#7006](https://github.com/paritytech/parity/pull/7006)). Existing PoA chains can go through a "maximum uncle count transition" to achieve more stability ([#7196](https://github.com/paritytech/parity/pull/7196)).
- Added Expanse's Byzantium hard-fork ([#7463](https://github.com/paritytech/parity/pull/7463)).
- Added support for Ellaism chain ([#7222](https://github.com/paritytech/parity/pull/7222)).
Further, users upgrading from 1.8 should acknowledge the following changes:
- Fixed DELEGATECALL's from/to field ([#7568](https://github.com/paritytech/parity/pull/7568)).
- Set zero nonce and gas price for calls by default ([#6954](https://github.com/paritytech/parity/pull/6954)).
- Create pending blocks with all transactions from the queue ([#6942](https://github.com/paritytech/parity/pull/6942)).
- Remove RPC parameter leniency now that Mist formats correctly ([#6651](https://github.com/paritytech/parity/pull/6651)). Parity stops accepting decimal-formatted block numbers and stops parsing the empty string as empty bytes.
- Public nodes do not support the user interface anymore. If you are running a public node, please stay on the 1.8 branch of the stable releases.
Additional noteworthy changes:
- `ethstore` and `ethkey` have been significantly improved ([#6961](https://github.com/paritytech/parity/pull/6961)):
- `ethstore` now supports brute forcing pre-sale wallets given a password list for recovery.
- `ethkey` now supports multi-threaded generation of prefix-matching addresses.
- `ethkey` now supports prefix-matching brain wallets.
- `ethkey` now supports brain-wallets recovery-phrases lookup. This helps to find a correct phrase if you know the address you want to get yet you made a typo backing the phrase up, or forgot a word.
Read more about Parity 1.9 in our [blog post](http://paritytech.io/velocity-the-fastest-parity-released/).
The full list of included changes:
- Add scroll when when too many accounts ([#7677](https://github.com/paritytech/parity/pull/7677)) ([#7679](https://github.com/paritytech/parity/pull/7679))
- Update installer.nsi
- Fix conditions in gitlab-test ([#7676](https://github.com/paritytech/parity/pull/7676))
- Fix conditions in gitlab-test
- Update gitlab-test.sh
- Remove cargo cache
- Backports to beta ([#7660](https://github.com/paritytech/parity/pull/7660))
- Improve handling of RocksDB corruption ([#7630](https://github.com/paritytech/parity/pull/7630))
- Kvdb-rocksdb: update rust-rocksdb version
- Kvdb-rocksdb: mark corruptions and attempt repair on db open
- Kvdb-rocksdb: better corruption detection on open
- Kvdb-rocksdb: add corruption_file_name const
- Kvdb-rocksdb: rename mark_corruption to check_for_corruption
- Hardening of CSP ([#7621](https://github.com/paritytech/parity/pull/7621))
- Fixed delegatecall's from/to ([#7568](https://github.com/paritytech/parity/pull/7568))
- Fixed delegatecall's from/to, closes [#7166](https://github.com/paritytech/parity/issues/7166)
- Added tests for delegatecall traces, [#7167](https://github.com/paritytech/parity/issues/7167)
- Light client RPCs ([#7603](https://github.com/paritytech/parity/pull/7603))
- Implement registrar.
- Implement eth_getCode
- Don't wait for providers.
- Don't wait for providers.
- Fix linting and wasm tests.
- Problem: AttachedProtocols don't get registered ([#7610](https://github.com/paritytech/parity/pull/7610))
- Fix Temporarily Invalid blocks handling ([#7613](https://github.com/paritytech/parity/pull/7613))
- Handle temporarily invalid blocks in sync.
- Fix tests.
- Fix configuration tests.
- Rename to warp barrier.
- Allow unsafe js eval on Parity Wallet. ([#8204](https://github.com/paritytech/parity/pull/8204))
- Update musicoin spec in line with gmc v2.6.2 ([#8242](https://github.com/paritytech/parity/pull/8242))
- Supress TemporaryInvalid verification failures. ([#8256](https://github.com/paritytech/parity/pull/8256))
- Include suicided accounts in state diff ([#8297](https://github.com/paritytech/parity/pull/8297))
- Include suicided accounts in state diff
- Shorten form match -> if let
- Test suicide trace diff in State
- Replace_home for password_files, reserved_peers and log_file ([#8324](https://github.com/paritytech/parity/pull/8324))
- Replace_home for password_files, reserved_peers and log_file
- Typo: arg_log_file is Option
- Enable UI by default, but only display info page.
- Fix test.
- Fix naming and remove old todo.
- Change "wallet" with "browser UI"
- Change name Wallet -> UI ([#8164](https://github.com/paritytech/parity/pull/8164)) ([#8205](https://github.com/paritytech/parity/pull/8205))
- Change name Wallet -> UI
- Make warning bold
- Backport [#8099](https://github.com/paritytech/parity/pull/8099) ([#8132](https://github.com/paritytech/parity/pull/8132))
- WASM libs ([#8220](https://github.com/paritytech/parity/pull/8220))
- Bump wasm libs ([#8171](https://github.com/paritytech/parity/pull/8171))
- Bump wasmi version ([#8209](https://github.com/paritytech/parity/pull/8209))
- Update hyper to 0.11.24 ([#8203](https://github.com/paritytech/parity/pull/8203))
- Updated jsonrpc to include latest backports (beta) ([#8181](https://github.com/paritytech/parity/pull/8181))
- Updated jsonrpc to include latest backports
- Update dependencies.
- Add docker build for beta ([#7671](https://github.com/paritytech/parity/pull/7671))
- Add docker build for beta
- Add cargo cache
- Fix snapcraft build for beta ([#7670](https://github.com/paritytech/parity/pull/7670))
- Update Parity.pkgproj
- update gitlab build from master
- Update references to dapp sources ([#7634](https://github.com/paritytech/parity/pull/7634)) ([#7636](https://github.com/paritytech/parity/pull/7636))
- Update tokenreg ([#7618](https://github.com/paritytech/parity/pull/7618)) ([#7619](https://github.com/paritytech/parity/pull/7619))
- Fix cache:key ([#7598](https://github.com/paritytech/parity/pull/7598))
- Make 1.9 beta ([#7533](https://github.com/paritytech/parity/pull/7533))
- Trigger js-precompiled ([#7535](https://github.com/paritytech/parity/pull/7535))
- RocksDB fix ([#7512](https://github.com/paritytech/parity/pull/7512))
- Update js-api ([#7510](https://github.com/paritytech/parity/pull/7510))
- Expose default gas price percentile configuration in CLI ([#7497](https://github.com/paritytech/parity/pull/7497))
- Use https connection ([#7503](https://github.com/paritytech/parity/pull/7503))
- More thorough changes detection ([#7472](https://github.com/paritytech/parity/pull/7472))
- Fix small layout issues ([#7500](https://github.com/paritytech/parity/pull/7500))
- Show all accounts on Topbar ([#7498](https://github.com/paritytech/parity/pull/7498))
- Update Parity Mainnet Bootnodes ([#7476](https://github.com/paritytech/parity/pull/7476))
- Fixed panic when io is not available for export block ([#7495](https://github.com/paritytech/parity/pull/7495))
- Advance AuRa step as far as we can and prevent invalid blocks. ([#7451](https://github.com/paritytech/parity/pull/7451))
- Update package-lock in js-old ([#7494](https://github.com/paritytech/parity/pull/7494))
- Update issue template and readme ([#7450](https://github.com/paritytech/parity/pull/7450))
- Update package-lock.json pinned versions ([#7492](https://github.com/paritytech/parity/pull/7492))
- Explicit pre-precompiled push checkout ([#7474](https://github.com/paritytech/parity/pull/7474))
- Trigger js-precompiled ([#7473](https://github.com/paritytech/parity/pull/7473))
- Expanse Byzantium update w/ correct metropolis difficulty increment divisor ([#7463](https://github.com/paritytech/parity/pull/7463))
- Updated icons ([#7469](https://github.com/paritytech/parity/pull/7469))
- Cleanup certifications ([#7454](https://github.com/paritytech/parity/pull/7454))
- Fix css lint (updated stylelint) ([#7471](https://github.com/paritytech/parity/pull/7471))
- Upgrade markdown-loader & marked ([#7467](https://github.com/paritytech/parity/pull/7467))
- Remove JS test for removed code ([#7461](https://github.com/paritytech/parity/pull/7461))
- Pull in dapp-status ([#7457](https://github.com/paritytech/parity/pull/7457))
- Bump openssl crate ([#7455](https://github.com/paritytech/parity/pull/7455))
- Signer updates from global Redux state ([#7452](https://github.com/paritytech/parity/pull/7452))
- Remove expanse chain ([#7437](https://github.com/paritytech/parity/pull/7437))
- Store tokens with repeatable id ([#7435](https://github.com/paritytech/parity/pull/7435))
- Strict config parsing ([#7433](https://github.com/paritytech/parity/pull/7433))
- Upgrade to RocksDB 5.8.8 and tune settings to reduce space amplification ([#7348](https://github.com/paritytech/parity/pull/7348))
- Fix status layout ([#7432](https://github.com/paritytech/parity/pull/7432))
- Fix tracing failed calls. ([#7412](https://github.com/paritytech/parity/pull/7412))
- Problem: sending any Whisper message fails ([#7421](https://github.com/paritytech/parity/pull/7421))
- Wait for future blocks in AuRa ([#7368](https://github.com/paritytech/parity/pull/7368))
- Fix final feature. ([#7426](https://github.com/paritytech/parity/pull/7426))
- Use RwLock for state DB ([#7425](https://github.com/paritytech/parity/pull/7425))
- Update branding on UI ([#7370](https://github.com/paritytech/parity/pull/7370))
- Changelog for 1.8.5 and 1.7.11 ([#7401](https://github.com/paritytech/parity/pull/7401))
- Added checking tx-type using transactions permission contract for miners ([#7359](https://github.com/paritytech/parity/pull/7359))
- Standalone dir crate, replaces [#7383](https://github.com/paritytech/parity/issues/7383) ([#7409](https://github.com/paritytech/parity/pull/7409))
- SecretStore: secretstore_signRawHash method ([#7336](https://github.com/paritytech/parity/pull/7336))
- SecretStore: return error 404 when there's no key shares for given key on all nodes ([#7331](https://github.com/paritytech/parity/pull/7331))
- SecretStore: PoA integration initial version ([#7101](https://github.com/paritytech/parity/pull/7101))
- Update bootnodes ([#7363](https://github.com/paritytech/parity/pull/7363))
- Fix default CORS settings. ([#7387](https://github.com/paritytech/parity/pull/7387))
- Fix version ([#7390](https://github.com/paritytech/parity/pull/7390))
- Wasm runtime update ([#7356](https://github.com/paritytech/parity/pull/7356))
- Parity-version pr reopen ([#7136](https://github.com/paritytech/parity/pull/7136))
- Get rid of clippy remainings. ([#7355](https://github.com/paritytech/parity/pull/7355))
- Avoid using ok_or with allocated argument ([#7357](https://github.com/paritytech/parity/pull/7357))
- Make accounts refresh time configurable. ([#7345](https://github.com/paritytech/parity/pull/7345))
- Enable traces for DEV chain ([#7327](https://github.com/paritytech/parity/pull/7327))
- Problem: AuRa's unsafeties around step duration ([#7282](https://github.com/paritytech/parity/pull/7282))
- Problem: Cargo.toml file contains [project] key ([#7346](https://github.com/paritytech/parity/pull/7346))
- Fix broken flex modal layouts ([#7343](https://github.com/paritytech/parity/pull/7343))
- Fix dappIcon & Fix Signer Pending ([#7338](https://github.com/paritytech/parity/pull/7338))
- Fix wallet token/badge icons not showing up ([#7333](https://github.com/paritytech/parity/pull/7333))
- Add Ellaism coin in chain config ([#7222](https://github.com/paritytech/parity/pull/7222))
- Update bootnodes ([#7296](https://github.com/paritytech/parity/pull/7296))
- Adds `personal_signTransaction` RPC method ([#6991](https://github.com/paritytech/parity/pull/6991))
- Fix double initialization of embeded providers. ([#7326](https://github.com/paritytech/parity/pull/7326))
- Transaction Pool re-implementation ([#6994](https://github.com/paritytech/parity/pull/6994))
- UI package bump ([#7318](https://github.com/paritytech/parity/pull/7318))
- Test framework and basic test for whisper ([#7011](https://github.com/paritytech/parity/pull/7011))
- CI js-precompiled trigger ([#7316](https://github.com/paritytech/parity/pull/7316))
- Fix inject.js & Signer store duplication ([#7299](https://github.com/paritytech/parity/pull/7299))
- Detect different node, same-key signing in aura ([#7245](https://github.com/paritytech/parity/pull/7245))
- New warp enodes ([#7287](https://github.com/paritytech/parity/pull/7287))
- CSS fixes for v1 ([#7285](https://github.com/paritytech/parity/pull/7285))
- Wallet subscriptions & refresh ([#7283](https://github.com/paritytech/parity/pull/7283))
- Update inject web3 dependencies ([#7286](https://github.com/paritytech/parity/pull/7286))
- Some padding around dapp image ([#7276](https://github.com/paritytech/parity/pull/7276))
- Expand available middleware methods ([#7275](https://github.com/paritytech/parity/pull/7275))
- Inject parity script to all dapps // Expand dapps to any ZIP file ([#7260](https://github.com/paritytech/parity/pull/7260))
- New Homepage ([#7266](https://github.com/paritytech/parity/pull/7266))
- Update kovan HF block number. ([#7259](https://github.com/paritytech/parity/pull/7259))
- CHANGELOG for 1.7.10 and 1.8.4 ([#7265](https://github.com/paritytech/parity/pull/7265))
- Remove extraneous id hashing ([#7269](https://github.com/paritytech/parity/pull/7269))
- Simplify status + content display overlaps/page fixing ([#7264](https://github.com/paritytech/parity/pull/7264))
- UI redirect to 127.0.0.1 when localhost requested ([#7236](https://github.com/paritytech/parity/pull/7236))
- Usability improvements to security token Dialog [#7112](https://github.com/paritytech/parity/issues/7112) ([#7134](https://github.com/paritytech/parity/pull/7134))
- Don't display unneeded notifications ([#7237](https://github.com/paritytech/parity/pull/7237))
- Reduce max block timestamp drift to 15 seconds ([#7240](https://github.com/paritytech/parity/pull/7240))
- Increase allowed time drift to 10s. ([#7238](https://github.com/paritytech/parity/pull/7238))
- Improve building from source ([#7239](https://github.com/paritytech/parity/pull/7239))
- Fix/Update method permissions ([#7233](https://github.com/paritytech/parity/pull/7233))
- Fix aura difficulty race ([#7198](https://github.com/paritytech/parity/pull/7198))
- Dependency updates ([#7226](https://github.com/paritytech/parity/pull/7226))
- Display all dapps (shell) & wallet tabs (v1) by default ([#7213](https://github.com/paritytech/parity/pull/7213))
- Rework dapps list ([#7206](https://github.com/paritytech/parity/pull/7206))
- Add contributing guidelines and code of conduct. ([#7157](https://github.com/paritytech/parity/pull/7157))
- Make Signing Requests more visible ([#7204](https://github.com/paritytech/parity/pull/7204))
- Send each log as a separate notification ([#7175](https://github.com/paritytech/parity/pull/7175))
- Deleting a mistake comment in calc difficulty ([#7154](https://github.com/paritytech/parity/pull/7154))
- Maximum uncle count transition ([#7196](https://github.com/paritytech/parity/pull/7196))
- Update FirstRun for UI-2 ([#7195](https://github.com/paritytech/parity/pull/7195))
- Update mocha import stubs ([#7191](https://github.com/paritytech/parity/pull/7191))
- Escape inifinite loop in estimte_gas ([#7075](https://github.com/paritytech/parity/pull/7075))
- New account selector UI in top bar ([#7179](https://github.com/paritytech/parity/pull/7179))
- Removed ethcore-util dependency from ethcore-network ([#7180](https://github.com/paritytech/parity/pull/7180))
- WASM test runner utility upgrade ([#7147](https://github.com/paritytech/parity/pull/7147))
- React 16 ([#7174](https://github.com/paritytech/parity/pull/7174))
- Assorted improvements for ethstore and ethkey ([#6961](https://github.com/paritytech/parity/pull/6961))
- Delete unused package.json (dist bundles) ([#7173](https://github.com/paritytech/parity/pull/7173))
- Remove *.css.map & *.js.map ([#7168](https://github.com/paritytech/parity/pull/7168))
- Use git flag to remove old js artifacts ([#7165](https://github.com/paritytech/parity/pull/7165))
- Cleanup JS build artifacts ([#7164](https://github.com/paritytech/parity/pull/7164))
- Fixes typo in user config path ([#7159](https://github.com/paritytech/parity/pull/7159))
- Pull in new dapp-{methods,visible} dapps ([#7150](https://github.com/paritytech/parity/pull/7150))
- WASM test runner utility ([#7142](https://github.com/paritytech/parity/pull/7142))
- WASM Remove blockhash error ([#7121](https://github.com/paritytech/parity/pull/7121))
- ECIP-1039: Monetary policy rounding specification ([#7067](https://github.com/paritytech/parity/pull/7067))
- Fixed `RotatingLogger` after migrating to new arrayvec ([#7129](https://github.com/paritytech/parity/pull/7129))
- Push to correct shell branch ([#7135](https://github.com/paritytech/parity/pull/7135))
- Update js-precompiled ref, trigger JS build ([#7132](https://github.com/paritytech/parity/pull/7132))
- Fixed build && test ([#7128](https://github.com/paritytech/parity/pull/7128))
- Update packages, pull in compiled-only repos ([#7125](https://github.com/paritytech/parity/pull/7125))
- Cleanup top bar, add Home icon for navigation ([#7118](https://github.com/paritytech/parity/pull/7118))
- WASM storage_read and storage_write don't return anything ([#7110](https://github.com/paritytech/parity/pull/7110))
- Local dapp development URL ([#7100](https://github.com/paritytech/parity/pull/7100))
- Remove unused and duplicated files in js-old ([#7082](https://github.com/paritytech/parity/pull/7082))
- Optimize & group dapp requests ([#7083](https://github.com/paritytech/parity/pull/7083))
- WASM parse payload from panics ([#7097](https://github.com/paritytech/parity/pull/7097))
- Fix no-default-features. ([#7096](https://github.com/paritytech/parity/pull/7096))
- Updated eth-secp256k1 ([#7090](https://github.com/paritytech/parity/pull/7090))
- Improve Github Issue Template ([#7099](https://github.com/paritytech/parity/pull/7099))
- Changes necessary to upload crates to crates.io ([#7020](https://github.com/paritytech/parity/pull/7020))
- Reopened 6860 - iterate over both buffered and unbuffered database entries ([#7048](https://github.com/paritytech/parity/pull/7048))
- SecretStore: servers set change session api ([#6925](https://github.com/paritytech/parity/pull/6925))
- Disable uncles by default ([#7006](https://github.com/paritytech/parity/pull/7006))
- Squashed ethcore-network changes which introduce error-chain ([#7040](https://github.com/paritytech/parity/pull/7040))
- Removed redundant imports ([#7057](https://github.com/paritytech/parity/pull/7057))
- CHANGELOG for 1.7.8, 1.7.9, 1.8.2, and 1.8.3 ([#7055](https://github.com/paritytech/parity/pull/7055))
- Properly display Signer errors (Snackbar display popup) ([#7053](https://github.com/paritytech/parity/pull/7053))
- Add the desktop file for the snap ([#7059](https://github.com/paritytech/parity/pull/7059))
- Small performance gain in allocations ([#7054](https://github.com/paritytech/parity/pull/7054))
- Bump JSON-RPC version ([#7051](https://github.com/paritytech/parity/pull/7051))
- Fix nonce reservation ([#7025](https://github.com/paritytech/parity/pull/7025))
- Fixed ethstore-cli output ([#7052](https://github.com/paritytech/parity/pull/7052))
- Add mui for embed compilation ([#7049](https://github.com/paritytech/parity/pull/7049))
- Update the snap metadata to keep working strictly confined ([#6993](https://github.com/paritytech/parity/pull/6993))
- Remove unused js packages (dapp cleanups) ([#7046](https://github.com/paritytech/parity/pull/7046))
- Gitlog location update ([#7042](https://github.com/paritytech/parity/pull/7042))
- Move git logging to .git-release.log ([#7041](https://github.com/paritytech/parity/pull/7041))
- Start from rust root in release update step ([#7039](https://github.com/paritytech/parity/pull/7039))
- Complete token merge, remove unused files ([#7037](https://github.com/paritytech/parity/pull/7037))
- Add missing cargo-push.sh shell variable ([#7036](https://github.com/paritytech/parity/pull/7036))
- Fix npm start script ([#7034](https://github.com/paritytech/parity/pull/7034))
- Update executable flags on release scripts ([#7035](https://github.com/paritytech/parity/pull/7035))
- Fix v1 precompiled ([#7033](https://github.com/paritytech/parity/pull/7033))
- Push precompiled to correct branch (v1) ([#7031](https://github.com/paritytech/parity/pull/7031))
- Update v1 Wallet Dapp ([#6935](https://github.com/paritytech/parity/pull/6935))
- WASM tests update ([#7018](https://github.com/paritytech/parity/pull/7018))
- Events in WASM runtime ([#6967](https://github.com/paritytech/parity/pull/6967))
- Adds validate_node_url() and refactors boot node check ([#6907](https://github.com/paritytech/parity/pull/6907)) ([#6970](https://github.com/paritytech/parity/pull/6970))
- Fix windows build (with ui rebuild) ([#7016](https://github.com/paritytech/parity/pull/7016))
- Make CLI arguments parsing more backwards compatible ([#7004](https://github.com/paritytech/parity/pull/7004))
- Fixes for parity-extension ([#6990](https://github.com/paritytech/parity/pull/6990))
- Update ethcore-bigint ([#6992](https://github.com/paritytech/parity/pull/6992))
- Get local transactions by hash in the light client ([#6874](https://github.com/paritytech/parity/pull/6874))
- Warn when blacklisted account present in store ([#6875](https://github.com/paritytech/parity/pull/6875))
- Skip nonce check for gas estimation ([#6997](https://github.com/paritytech/parity/pull/6997))
- Creating pending block with all transactions from the queue ([#6942](https://github.com/paritytech/parity/pull/6942))
- Removes `MAX_TX_TO_IMPORT` from `ChainSync` ([#6976](https://github.com/paritytech/parity/pull/6976))
- SecretStore: versioned keys ([#6910](https://github.com/paritytech/parity/pull/6910))
- Removes `FUTURE_QUEUE_LIMITS_SHIFT` ([#6962](https://github.com/paritytech/parity/pull/6962))
- Set zero nonce and gas price for calls by default ([#6954](https://github.com/paritytech/parity/pull/6954))
- Add hint in ActionParams for splitting code/data ([#6957](https://github.com/paritytech/parity/pull/6957))
- Return decoded seal fields. ([#6932](https://github.com/paritytech/parity/pull/6932))
- Fix serialization of status in transaction receipts. ([#6926](https://github.com/paritytech/parity/pull/6926))
- Reserve nonces for signing ([#6834](https://github.com/paritytech/parity/pull/6834))
- Windows fixes ([#6921](https://github.com/paritytech/parity/pull/6921))
- Don't add {css,js}.map from dapps ([#6931](https://github.com/paritytech/parity/pull/6931))
- Fix JSON tracing for sub-calls. ([#6842](https://github.com/paritytech/parity/pull/6842))
- Shell updates (bonds, updated Dapps) ([#6897](https://github.com/paritytech/parity/pull/6897))
- Fix [#6228](https://github.com/paritytech/parity/issues/6228): do not display eth price in cli for etc ([#6877](https://github.com/paritytech/parity/pull/6877))
- Fix mining help ([#6885](https://github.com/paritytech/parity/pull/6885))
- Refactor static context check in CREATE. ([#6886](https://github.com/paritytech/parity/pull/6886))
- Cleanup some configuration options ([#6878](https://github.com/paritytech/parity/pull/6878))
- Fix serialization of non-localized transactions ([#6868](https://github.com/paritytech/parity/pull/6868))
- Updated ntp to version 0.3 ([#6854](https://github.com/paritytech/parity/pull/6854))
- Align README with 1.8 and prepare CHANGELOG with 1.8.1 ([#6833](https://github.com/paritytech/parity/pull/6833))
- Return error on timed unlock ([#6777](https://github.com/paritytech/parity/pull/6777))
- Fix dapps tests in master ([#6866](https://github.com/paritytech/parity/pull/6866))
- Ethstore optimizations ([#6827](https://github.com/paritytech/parity/pull/6827))
- Add ECIP1017 to Morden config ([#6810](https://github.com/paritytech/parity/pull/6810))
- Remove all package publishing to npm ([#6838](https://github.com/paritytech/parity/pull/6838))
- Util crates use tempdir crate instead of devtools to create temp path ([#6807](https://github.com/paritytech/parity/pull/6807))
- Trigger js build ([#6836](https://github.com/paritytech/parity/pull/6836))
- Clean-up scripts. ([#6832](https://github.com/paritytech/parity/pull/6832))
- Tweaked snapshot sync threshold ([#6829](https://github.com/paritytech/parity/pull/6829))
- Integrate UI 2 ([#6819](https://github.com/paritytech/parity/pull/6819))
- Refresh cached tokens based on registry info & random balances ([#6818](https://github.com/paritytech/parity/pull/6818))
- Change keypath derivation logic ([#6815](https://github.com/paritytech/parity/pull/6815))
- Refactors journaldb as a separate crate ([#6801](https://github.com/paritytech/parity/pull/6801))
- Trigger UI build. ([#6817](https://github.com/paritytech/parity/pull/6817))
- Bumped more crate versions ([#6809](https://github.com/paritytech/parity/pull/6809))
- Fix RPC compilation warnings. ([#6808](https://github.com/paritytech/parity/pull/6808))
- Remove internal ipc ([#6795](https://github.com/paritytech/parity/pull/6795))
- Consistent KeyValueDB errors ([#6792](https://github.com/paritytech/parity/pull/6792))
- Squash remaining warnings ([#6789](https://github.com/paritytech/parity/pull/6789))
- Forward-port [#6754](https://github.com/paritytech/parity/issues/6754) [#6755](https://github.com/paritytech/parity/issues/6755) ([#6785](https://github.com/paritytech/parity/pull/6785))
- Removed duplicated versions of clippy ([#6776](https://github.com/paritytech/parity/pull/6776))
- Updated ethabi to version 4.0 ([#6742](https://github.com/paritytech/parity/pull/6742))
- Updated rpc_cli and parity to rpassword 1.0 ([#6774](https://github.com/paritytech/parity/pull/6774))
- Fix sign data typo ([#6750](https://github.com/paritytech/parity/pull/6750))
- Refactoring/cache 6693 ([#6772](https://github.com/paritytech/parity/pull/6772))
- Fix CHANGLOG for 1.8.0 ([#6751](https://github.com/paritytech/parity/pull/6751))
- Removes redundant `mut` in service.rs.in ([#6775](https://github.com/paritytech/parity/pull/6775))
- Remove redundant `mut` ([#6773](https://github.com/paritytech/parity/pull/6773))
- Fixed kovan chain validation ([#6758](https://github.com/paritytech/parity/pull/6758))
- Removed redundant evm deps ([#6757](https://github.com/paritytech/parity/pull/6757))
- Fixed modexp gas calculation overflow ([#6741](https://github.com/paritytech/parity/pull/6741))
- Use cc 1.0 instead of gcc ([#6733](https://github.com/paritytech/parity/pull/6733))
- Version bump to 1.9.0 ([#6727](https://github.com/paritytech/parity/pull/6727))
- Fix badges not showing up ([#6730](https://github.com/paritytech/parity/pull/6730))
## Parity [v1.10.0](https://github.com/paritytech/parity/releases/tag/v1.10.0) (2018-03-22)
### Previous releases
This is the Parity 1.10.0-beta release! Cool!
### Disabling the Parity Wallet
The **Parity Wallet (a.k.a. "UI") is now disabled by default**. We are preparing to split the wallet from the core client.
To reactivate the parity wallet, you have to run Parity either with `parity --force-ui` (not recommended) or `parity ui` (deprecated) from the command line. Or, if you feel super fancy and want to test our pre-releases of the stand-alone electron wallet, head over to the [Parity-JS repositories and check the releases](https://github.com/Parity-JS/shell/releases).
Further reading:
- [Docs: Parity Wallet](https://wiki.parity.io/Parity-Wallet)
- [Docs: How to customize Parity UI?](https://wiki.parity.io/FAQ-Customize-Parity-UI.html)
- [Github: Parity-JS](https://github.com/parity-js)
### Introducing the Wasm VM
We are excited to announce support for **Wasm Smart Contracts on Kovan network**. The hard-fork to activate the Wasm-VM will take place on block `6_600_000`.
To enable Wasm contracts on your custom network, just schedule a `wasmActivationTransition` at your favorite block number (e.g., `42`, `666`, or `0xbada55`). To hack your first Wasm smart contracts in Rust, have a look at the [Parity Wasm Tutorials](https://github.com/paritytech/pwasm-tutorial).
Further reading:
- [Docs: WebAssembly (wasm)](https://wiki.parity.io/WebAssembly-Home)
- [Docs: Wasm VM Design](https://wiki.parity.io/WebAssembly-Design)
- [Docs: Wasm tutorials and examples](https://wiki.parity.io/WebAssembly-Links)
### Empty step messages in PoA
To **reduce blockchain bloat, proof-of-authority networks can now enable _empty step messages_ which replace empty blocks**. Each step message will be signed and broadcasted by the issuing authorities, and included and rewarded in the next non-empty block.
To enable empty step messages, set the `emptyStepsTransition` to your favorite block number. You can also specify a maximum number of empty steps with `maximumEmptySteps` in your chain spec.
### Other noteworthy changes
We removed the old database migrations from 2016. In case you upgrade Parity from a really, really old version, you will have to reset your database manually first with `parity <options> db kill`.
We fixed DELEGATECALL `from` and `to` fields, see [#7166](https://github.com/paritytech/parity/issues/7166).
We reduced the default USD per transaction value to 0.0001. Thanks, @MysticRyuujin!
The Musicoin chain is now enabled with Byzantium features starting at block `2_222_222`.
### Overview of all changes included
The full list of included changes:
- Re-enable signer, even with no UI. ([#8167](https://github.com/paritytech/parity/pull/8167)) ([#8168](https://github.com/paritytech/parity/pull/8168))
- Re-enable signer, even with no UI.
- Fix message.
- Beta Backports ([#8136](https://github.com/paritytech/parity/pull/8136))
- Support parity protocol. ([#8035](https://github.com/paritytech/parity/pull/8035))
- updater: apply exponential backoff after download failure ([#8059](https://github.com/paritytech/parity/pull/8059))
- updater: apply exponential backoff after download failure
- updater: reset backoff on new release
- Max code size on Kovan ([#8067](https://github.com/paritytech/parity/pull/8067))
- Enable code size limit on kovan
- Fix formatting.
- Limit incoming connections. ([#8060](https://github.com/paritytech/parity/pull/8060))
- Limit ingress connections
- Optimized handshakes logging
- WASM libraries bump ([#7970](https://github.com/paritytech/parity/pull/7970))
- update wasmi, parity-wasm, wasm-utils to latest version
- Update to new wasmi & error handling
- also utilize new stack limiter
- fix typo
- replace dependency url
- Cargo.lock update
- add some dos protection ([#8084](https://github.com/paritytech/parity/pull/8084))
- revert removing blooms ([#8066](https://github.com/paritytech/parity/pull/8066))
- Revert "fix traces, removed bloomchain crate, closes [#7228](https://github.com/paritytech/parity/issues/7228), closes [#7167](https://github.com/paritytech/parity/issues/7167)"
- Revert "fixed broken logs ([#7934](https://github.com/paritytech/parity/pull/7934))"
- fixed broken logs
- bring back old lock order
- remove migration v13
- revert CURRENT_VERSION to 12 in migration.rs
- more dos protection ([#8104](https://github.com/paritytech/parity/pull/8104))
- Const time comparison ([#8113](https://github.com/paritytech/parity/pull/8113))
- Use `subtle::slices_equal` for constant time comparison.
- Also update the existing version of subtle in `ethcrypto` from 0.1 to 0.5
- Test specifically for InvalidPassword error.
- fix trace filter returning returning unrelated reward calls, closes #8070 ([#8098](https://github.com/paritytech/parity/pull/8098))
- network: init discovery using healthy nodes ([#8061](https://github.com/paritytech/parity/pull/8061))
- network: init discovery using healthy nodes
- network: fix style grumble
- network: fix typo
- Postpone Kovan hard fork ([#8137](https://github.com/paritytech/parity/pull/8137))
- ethcore: postpone Kovan hard fork
- util: update version fork metadata
- Disable UI by default. ([#8105](https://github.com/paritytech/parity/pull/8105))
- dapps: update parity-ui dependencies ([#8160](https://github.com/paritytech/parity/pull/8160))
- Probe changes one step deeper ([#8134](https://github.com/paritytech/parity/pull/8134)) ([#8135](https://github.com/paritytech/parity/pull/8135))
- Beta backports ([#8053](https://github.com/paritytech/parity/pull/8053))
- CI: Fix cargo cache ([#7968](https://github.com/paritytech/parity/pull/7968))
- Fix cache
- Only clean locked cargo cache on windows
- fixed ethstore sign ([#8026](https://github.com/paritytech/parity/pull/8026))
- fixed parsing ethash seals and verify_block_undordered ([#8031](https://github.com/paritytech/parity/pull/8031))
- fix for verify_block_basic crashing on invalid transaction rlp ([#8032](https://github.com/paritytech/parity/pull/8032))
- fix cache & snapcraft CI build ([#8052](https://github.com/paritytech/parity/pull/8052))
- Add MCIP-6 Byzyantium transition to Musicoin spec ([#7841](https://github.com/paritytech/parity/pull/7841))
- Add test chain spec for musicoin byzantium testnet
- Add MCIP-6 Byzyantium transition to Musicoin spec
- Update mcip6_byz.json
- ethcore: update musicoin byzantium block number
- ethcore: update musicoin bootnodes
- Update musicoin.json
- More bootnodes.
- Make 1.10 beta ([#8022](https://github.com/paritytech/parity/pull/8022))
- Make 1.10 beta
- Fix gitlab builds
- SecretStore: secretstore_generateDocumentKey RPC ([#7864](https://github.com/paritytech/parity/pull/7864))
- SecretStore: ECDSA session for cases when 2*t < N ([#7739](https://github.com/paritytech/parity/pull/7739))
- bump tiny-keccak ([#8019](https://github.com/paritytech/parity/pull/8019))
- Remove un-necessary comment ([#8014](https://github.com/paritytech/parity/pull/8014))
- clean up account fmt::Debug ([#7983](https://github.com/paritytech/parity/pull/7983))
- improve quality of vote_collector module ([#7984](https://github.com/paritytech/parity/pull/7984))
- ExecutedBlock cleanup ([#7991](https://github.com/paritytech/parity/pull/7991))
- Hardware-wallet/usb-subscribe-refactor ([#7860](https://github.com/paritytech/parity/pull/7860))
- remove wildcard imports from views, make tests more idiomatic ([#7986](https://github.com/paritytech/parity/pull/7986))
- moved PerfTimer to a separate crate - "trace-time" ([#7985](https://github.com/paritytech/parity/pull/7985))
- clean up ethcore::spec module imports ([#7990](https://github.com/paritytech/parity/pull/7990))
- rpc: don't include current block in new_block_filter ([#7982](https://github.com/paritytech/parity/pull/7982))
- fix traces, removed bloomchain crate ([#7979](https://github.com/paritytech/parity/pull/7979))
- simplify compression and move it out of rlp crate ([#7957](https://github.com/paritytech/parity/pull/7957))
- removed old migrations ([#7974](https://github.com/paritytech/parity/pull/7974))
- Reject too large packets in snapshot sync. ([#7977](https://github.com/paritytech/parity/pull/7977))
- fixed broken logs ([#7934](https://github.com/paritytech/parity/pull/7934))
- Increase max download limit to 128MB ([#7965](https://github.com/paritytech/parity/pull/7965))
- Calculate proper keccak256/sha3 using parity. ([#7953](https://github.com/paritytech/parity/pull/7953))
- Add changelog for 1.8.10 stable and 1.9.3 beta ([#7947](https://github.com/paritytech/parity/pull/7947))
- kvdb-rocksdb: remove buffered operations when committing transaction ([#7950](https://github.com/paritytech/parity/pull/7950))
- Bump WebSockets ([#7952](https://github.com/paritytech/parity/pull/7952))
- removed redundant Bloom conversions ([#7932](https://github.com/paritytech/parity/pull/7932))
- simplify RefInfo fmt ([#7929](https://github.com/paritytech/parity/pull/7929))
- Kovan WASM fork code ([#7849](https://github.com/paritytech/parity/pull/7849))
- bring back trie and triehash benches ([#7926](https://github.com/paritytech/parity/pull/7926))
- removed redundant PodAccount::new method ([#7928](https://github.com/paritytech/parity/pull/7928))
- removed dummy wrapper structure - LogGroupPosition ([#7922](https://github.com/paritytech/parity/pull/7922))
- spec: Validate required divisor fields are not 0 ([#7933](https://github.com/paritytech/parity/pull/7933))
- simplify Client::filter_traces method ([#7936](https://github.com/paritytech/parity/pull/7936))
- gitlab cache ([#7921](https://github.com/paritytech/parity/pull/7921))
- Fix a division by zero in light client RPC handler ([#7917](https://github.com/paritytech/parity/pull/7917))
- triehash optimisations ([#7920](https://github.com/paritytech/parity/pull/7920))
- removed redundant Blockchain::db method ([#7919](https://github.com/paritytech/parity/pull/7919))
- removed redundant Blockchain::rewind method ([#7918](https://github.com/paritytech/parity/pull/7918))
- Pending transactions subscription ([#7906](https://github.com/paritytech/parity/pull/7906))
- removed redundant otry! macro from ethcore ([#7916](https://github.com/paritytech/parity/pull/7916))
- Make block generator easier to use ([#7888](https://github.com/paritytech/parity/pull/7888))
- ECIP 1041 - Remove Difficulty Bomb ([#7905](https://github.com/paritytech/parity/pull/7905))
- Fix CSP for dapps that require eval. ([#7867](https://github.com/paritytech/parity/pull/7867))
- Fix gitlab ([#7901](https://github.com/paritytech/parity/pull/7901))
- Gitlb snap master patch ([#7900](https://github.com/paritytech/parity/pull/7900))
- fix snap build master ([#7896](https://github.com/paritytech/parity/pull/7896))
- Fix wallet import ([#7873](https://github.com/paritytech/parity/pull/7873))
- Fix snapcraft nightly ([#7884](https://github.com/paritytech/parity/pull/7884))
- Add a timeout for light client sync requests ([#7848](https://github.com/paritytech/parity/pull/7848))
- SecretStore: fixed test ([#7878](https://github.com/paritytech/parity/pull/7878))
- Fix checksums and auto-update push ([#7846](https://github.com/paritytech/parity/pull/7846))
- Forward-port snap fixes ([#7831](https://github.com/paritytech/parity/pull/7831))
- Update gitlab-test.sh ([#7883](https://github.com/paritytech/parity/pull/7883))
- Fix installer binary names for macos and windows ([#7881](https://github.com/paritytech/parity/pull/7881))
- Fix string typo: "develoopment" -> "development" ([#7874](https://github.com/paritytech/parity/pull/7874))
- Update the instructions to install the stable snap ([#7876](https://github.com/paritytech/parity/pull/7876))
- SecretStore: 'broadcast' decryption session ([#7843](https://github.com/paritytech/parity/pull/7843))
- Flush keyfiles. Resolves #7632 ([#7868](https://github.com/paritytech/parity/pull/7868))
- Read registry_address from given block ([#7866](https://github.com/paritytech/parity/pull/7866))
- Clean up docs formatting for Wasm runtime ([#7869](https://github.com/paritytech/parity/pull/7869))
- WASM: Disable internal memory ([#7842](https://github.com/paritytech/parity/pull/7842))
- Update gitlab-build.sh ([#7855](https://github.com/paritytech/parity/pull/7855))
- ethabi version 5 ([#7723](https://github.com/paritytech/parity/pull/7723))
- Light client: randomize the peer we dispatch requests to ([#7844](https://github.com/paritytech/parity/pull/7844))
- Store updater metadata in a single place ([#7832](https://github.com/paritytech/parity/pull/7832))
- Add new EF ropstens nodes. ([#7824](https://github.com/paritytech/parity/pull/7824))
- refactor stratum to remove retain cycle ([#7827](https://github.com/paritytech/parity/pull/7827))
- Bump jsonrpc. ([#7828](https://github.com/paritytech/parity/pull/7828))
- Add binary identifiers and sha256sum to builds ([#7830](https://github.com/paritytech/parity/pull/7830))
- Update references to UI shell & wallet ([#7808](https://github.com/paritytech/parity/pull/7808))
- Adjust storage update evm-style ([#7812](https://github.com/paritytech/parity/pull/7812))
- Updated WASM Runtime & new interpreter (wasmi) ([#7796](https://github.com/paritytech/parity/pull/7796))
- SecretStore: ignore removed authorities when running auto-migration ([#7674](https://github.com/paritytech/parity/pull/7674))
- Fix build ([#7807](https://github.com/paritytech/parity/pull/7807))
- Move js & js-old code to github.com/parity-js ([#7685](https://github.com/paritytech/parity/pull/7685))
- More changelogs :) ([#7782](https://github.com/paritytech/parity/pull/7782))
- Actualized API set in help ([#7790](https://github.com/paritytech/parity/pull/7790))
- Removed obsolete file ([#7788](https://github.com/paritytech/parity/pull/7788))
- Update ropsten bootnodes ([#7776](https://github.com/paritytech/parity/pull/7776))
- CHANGELOG for 1.9.1 and 1.8.8 ([#7775](https://github.com/paritytech/parity/pull/7775))
- Enable byzantium features on non-ethash chains ([#7753](https://github.com/paritytech/parity/pull/7753))
- Fix client not being dropped on shutdown ([#7695](https://github.com/paritytech/parity/pull/7695))
- Filter-out nodes.json ([#7716](https://github.com/paritytech/parity/pull/7716))
- Removes redundant parentheses ([#7721](https://github.com/paritytech/parity/pull/7721))
- Transaction-pool fixes ([#7741](https://github.com/paritytech/parity/pull/7741))
- More visible download link in README.md ([#7707](https://github.com/paritytech/parity/pull/7707))
- Changelog for 1.9.0 ([#7664](https://github.com/paritytech/parity/pull/7664))
- Add scroll when too many accounts ([#7677](https://github.com/paritytech/parity/pull/7677))
- SecretStore: return HTTP 403 (access denied) if consensus is unreachable ([#7656](https://github.com/paritytech/parity/pull/7656))
- Moved StopGaurd to it's own crate ([#7635](https://github.com/paritytech/parity/pull/7635))
## Previous releases
- [CHANGELOG-1.9](docs/CHANGELOG-1.9.md) (_stable_)
- [CHANGELOG-1.8](docs/CHANGELOG-1.8.md) (EOL: 2018-03-22)
- [CHANGELOG-1.8](docs/CHANGELOG-1.8.md) (_stable_)
- [CHANGELOG-1.7](docs/CHANGELOG-1.7.md) (EOL: 2018-01-25)
- [CHANGELOG-1.6](docs/CHANGELOG-1.6.md) (EOL: 2017-10-15)
- [CHANGELOG-1.5](docs/CHANGELOG-1.5.md) (EOL: 2017-07-28)

1823
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"
# NOTE Make sure to update util/version/Cargo.toml as well
version = "1.11.6"
version = "1.10.4"
license = "GPL-3.0"
authors = ["Parity Technologies <admin@parity.io>"]
@@ -14,14 +14,15 @@ docopt = "0.8"
clap = "2"
term_size = "0.3"
textwrap = "0.9"
time = "0.1"
num_cpus = "1.2"
number_prefix = "0.2"
rpassword = "1.0"
semver = "0.9"
semver = "0.6"
ansi_term = "0.10"
parking_lot = "0.5"
regex = "0.2"
atty = "0.2.8"
isatty = "0.1"
toml = "0.4"
serde = "1.0"
serde_json = "1.0"
@@ -29,21 +30,21 @@ serde_derive = "1.0"
futures = "0.1"
futures-cpupool = "0.1"
fdlimit = "0.1"
ws2_32-sys = "0.2"
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-1.10" }
ethsync = { path = "sync" }
ethcore = { path = "ethcore" }
ethcore-bytes = { path = "util/bytes" }
ethcore-io = { path = "util/io" }
ethcore-light = { path = "ethcore/light" }
ethcore-logger = { path = "logger" }
ethcore-migrations = { path = "ethcore/migrations" }
ethcore-miner = { path = "miner" }
ethcore-network = { path = "util/network" }
ethcore-private-tx = { path = "ethcore/private-tx" }
ethcore-service = { path = "ethcore/service" }
ethcore-stratum = { path = "ethcore/stratum" }
ethcore-sync = { path = "ethcore/sync" }
ethcore-stratum = { path = "stratum" }
ethcore-transaction = { path = "ethcore/transaction" }
ethereum-types = "0.3"
ethereum-types = "0.2"
node-filter = { path = "ethcore/node_filter" }
ethkey = { path = "ethkey" }
node-health = { path = "dapps/node-health" }
@@ -62,17 +63,14 @@ path = { path = "util/path" }
dir = { path = "util/dir" }
panic_hook = { path = "util/panic_hook" }
keccak-hash = { path = "util/hash" }
migration-rocksdb = { path = "util/migration-rocksdb" }
migration = { path = "util/migration" }
kvdb = { path = "util/kvdb" }
kvdb-rocksdb = { path = "util/kvdb-rocksdb" }
journaldb = { path = "util/journaldb" }
mem = { path = "util/mem" }
parity-dapps = { path = "dapps", optional = true }
ethcore-secretstore = { path = "secret_store", optional = true }
registrar = { path = "registrar" }
[build-dependencies]
rustc_version = "0.2"
@@ -80,13 +78,12 @@ rustc_version = "0.2"
pretty_assertions = "0.1"
ipnetwork = "0.12.6"
tempdir = "0.3"
fake-fetch = { path = "util/fake-fetch" }
[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3.4", features = ["winsock2", "winuser", "shellapi"] }
winapi = "0.2"
[target.'cfg(not(windows))'.dependencies]
daemonize = { git = "https://github.com/paritytech/daemonize" }
daemonize = "0.2"
[features]
default = ["ui-precompiled"]
@@ -100,6 +97,7 @@ ui-precompiled = [
]
ui-enabled = ["dapps"]
dapps = ["parity-dapps"]
jit = ["ethcore/jit"]
json-tests = ["ethcore/json-tests"]
test-heavy = ["ethcore/test-heavy"]
evm-debug = ["ethcore/evm-debug"]
@@ -123,6 +121,7 @@ panic = "abort"
[workspace]
members = [
"chainspec",
"dapps/js-glue",
"ethcore/wasm/run",
"ethcore/types",
"ethkey/cli",
@@ -131,8 +130,5 @@ members = [
"miner",
"transaction-pool",
"whisper",
"whisper/cli",
"util/rlp_compress"
]
[patch.crates-io]
ring = { git = "https://github.com/paritytech/ring" }

View File

@@ -21,7 +21,7 @@ Or join our community on Matrix:
Official website: https://parity.io
Be sure to check out [our wiki](https://wiki.parity.io) for more information.
Be sure to check out [our wiki](https://paritytech.github.io/wiki/) and the [internal documentation](https://paritytech.github.io/parity/ethcore/index.html) for more information.
----
@@ -29,15 +29,13 @@ Be sure to check out [our wiki](https://wiki.parity.io) for more information.
Parity's goal is to be the fastest, lightest, and most secure Ethereum client. We are developing Parity using the sophisticated and cutting-edge Rust programming language. Parity is licensed under the GPLv3, and can be used for all your Ethereum needs.
Parity comes with a built-in wallet, to install it please follow [these instructions](https://wiki.parity.io/Parity-Wallet). It includes various functionality allowing you to:
Parity comes with a built-in wallet. To access [Parity Wallet](http://web3.site/) simply go to http://web3.site/ (if you don't have access to the internet, but still want to use the service, you can also use http://127.0.0.1:8180/). It includes various functionality allowing you to:
- create and manage your Ethereum accounts;
- manage your Ether and any Ethereum tokens;
- create and register your own tokens;
- and much more.
From Parity Ethereum client version >=1.10, the User Interface (UI) is accessible in a separate application called Parity UI. To keep using the UI in the browser (deprecated), [follow these steps](https://wiki.parity.io/FAQ-Basic-Operations,-Configuration,-and-Synchronization.md#the-parity-ui-application-isnt-working-the-way-i-want).
By default, Parity will also run a JSONRPC server on `127.0.0.1:8545` and a websockets server on `127.0.0.1:8546`. This is fully configurable and supports a number of APIs.
If you run into an issue while using Parity, feel free to file one in this repository or hop on our [Gitter](https://gitter.im/paritytech/parity) or [Riot](https://riot.im/app/#/group/+parity:matrix.parity.io) chat room to ask a question. We are glad to help!
@@ -75,11 +73,7 @@ We recommend installing Rust through [rustup](https://www.rustup.rs/). If you do
$ rustup default stable-x86_64-pc-windows-msvc
```
Once you have rustup installed, then you need to install:
* [Perl](https://www.perl.org)
* [Yasm](http://yasm.tortall.net)
Make sure that these binaries are in your `PATH`. After that you should be able to build parity from source.
Once you have rustup, install Parity or download and build from source
----

View File

@@ -1,7 +1,7 @@
[package]
description = "Parity Dapps crate"
name = "parity-dapps"
version = "1.11.0"
version = "1.9.0"
license = "GPL-3.0"
authors = ["Parity Technologies <admin@parity.io>"]
@@ -22,14 +22,14 @@ serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
unicase = "1.4"
zip = { version = "0.3", default-features = false, features = ["deflate"] }
zip = { version = "0.1", default-features = false }
itertools = "0.5"
jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.11" }
jsonrpc-http-server = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.11" }
jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.10" }
jsonrpc-http-server = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.10" }
ethcore-bytes = { path = "../util/bytes" }
ethereum-types = "0.3"
ethereum-types = "0.2"
fetch = { path = "../util/fetch" }
node-health = { path = "./node-health" }
parity-hash-fetch = { path = "../hash-fetch" }
@@ -38,7 +38,6 @@ parity-ui = { path = "./ui" }
parity-ui-deprecation = { path = "./ui-deprecation" }
keccak-hash = { path = "../util/hash" }
parity-version = { path = "../util/version" }
registrar = { path = "../registrar" }
[dev-dependencies]
env_logger = "0.4"

View File

@@ -17,7 +17,7 @@
//! Reporting node's health.
use std::sync::Arc;
use std::time::Duration;
use std::time;
use futures::Future;
use futures::sync::oneshot;
use types::{HealthInfo, HealthStatus, Health};
@@ -26,7 +26,7 @@ use parity_reactor::Remote;
use parking_lot::Mutex;
use {SyncStatus};
const TIMEOUT: Duration = Duration::from_secs(5);
const TIMEOUT_SECS: u64 = 5;
const PROOF: &str = "Only one closure is invoked.";
/// A struct enabling you to query for node's health.
@@ -53,11 +53,11 @@ impl NodeHealth {
let tx = Arc::new(Mutex::new(Some(tx)));
let tx2 = tx.clone();
self.remote.spawn_with_timeout(
move |_| time.then(move |result| {
move || time.then(move |result| {
let _ = tx.lock().take().expect(PROOF).send(Ok(result));
Ok(())
}),
TIMEOUT,
time::Duration::from_secs(TIMEOUT_SECS),
move || {
let _ = tx2.lock().take().expect(PROOF).send(Err(()));
},

View File

@@ -21,7 +21,7 @@ use std::path::PathBuf;
use ethereum_types::H256;
use fetch;
use futures_cpupool::CpuPool;
use hash::keccak_pipe;
use hash::keccak_buffer;
use mime_guess::Mime;
use apps::manifest::{MANIFEST_FILENAME, deserialize_manifest, serialize_manifest, Manifest};
@@ -55,15 +55,15 @@ fn write_response_and_check_hash(
// Now write the response
let mut file = io::BufWriter::new(fs::File::create(&content_path)?);
let mut reader = io::BufReader::new(fetch::BodyReader::new(response));
let hash = keccak_pipe(&mut reader, &mut file)?;
let mut file = file.into_inner()?;
io::copy(&mut reader, &mut file)?;
file.flush()?;
// Validate hash
// TODO [ToDr] calculate keccak in-flight while reading the response
let mut file = io::BufReader::new(fs::File::open(&content_path)?);
let hash = keccak_buffer(&mut file)?;
if id == hash {
// The writing above changed the file Read position, which we need later. So we just create a new file handle
// here.
Ok((fs::File::open(&content_path)?, content_path))
Ok((file.into_inner(), content_path))
} else {
Err(ValidationError::HashMismatch {
expected: id,
@@ -266,9 +266,3 @@ impl From<zip::result::ZipError> for ValidationError {
ValidationError::Zip(err)
}
}
impl From<io::IntoInnerError<io::BufWriter<fs::File>>> for ValidationError {
fn from(err: io::IntoInnerError<io::BufWriter<fs::File>>) -> Self {
ValidationError::Io(err.into())
}
}

View File

@@ -24,7 +24,7 @@ use fetch::{self, Fetch};
use futures::sync::oneshot;
use futures::{self, Future};
use futures_cpupool::CpuPool;
use hyper::{self, StatusCode};
use hyper::{self, Method, StatusCode};
use parking_lot::Mutex;
use endpoint::{self, EndpointPath};
@@ -32,7 +32,7 @@ use handlers::{ContentHandler, StreamingHandler};
use page::local;
use {Embeddable};
const FETCH_TIMEOUT: Duration = Duration::from_secs(300);
const FETCH_TIMEOUT: u64 = 300;
pub enum ValidatorResponse {
Local(local::Dapp),
@@ -57,7 +57,7 @@ impl Default for FetchControl {
FetchControl {
abort: Arc::new(AtomicBool::new(false)),
listeners: Arc::new(Mutex::new(Vec::new())),
deadline: Instant::now() + FETCH_TIMEOUT,
deadline: Instant::now() + Duration::from_secs(FETCH_TIMEOUT),
}
}
}
@@ -193,7 +193,7 @@ impl Errors {
ContentHandler::error(
StatusCode::GatewayTimeout,
"Download Timeout",
&format!("Could not fetch content within {} seconds.", FETCH_TIMEOUT.as_secs()),
&format!("Could not fetch content within {} seconds.", FETCH_TIMEOUT),
None,
self.embeddable_on.clone(),
)
@@ -261,7 +261,7 @@ impl ContentFetcherHandler {
// Validation of method
let status = match *method {
// Start fetching content
hyper::Method::Get => {
Method::Get => {
trace!(target: "dapps", "Fetching content from: {:?}", url);
FetchState::InProgress(Self::fetch_content(
pool,
@@ -295,7 +295,7 @@ impl ContentFetcherHandler {
) -> Box<Future<Item=FetchState, Error=()> + Send> {
// Start fetching the content
let pool2 = pool.clone();
let future = fetch.get(url, abort.into()).then(move |result| {
let future = fetch.fetch(url, abort.into()).then(move |result| {
trace!(target: "dapps", "Fetching content finished. Starting validation: {:?}", result);
Ok(match result {
Ok(response) => match installer.validate_and_install(response) {

View File

@@ -42,7 +42,6 @@ extern crate parity_ui;
extern crate parity_ui_deprecation;
extern crate keccak_hash as hash;
extern crate parity_version;
extern crate registrar;
#[macro_use]
extern crate futures;
@@ -82,7 +81,7 @@ use parking_lot::RwLock;
use fetch::Fetch;
use node_health::NodeHealth;
pub use registrar::{RegistrarClient, Asynchronous};
pub use hash_fetch::urlhint::ContractClient;
pub use node_health::SyncStatus;
@@ -157,7 +156,7 @@ impl Middleware {
pool: CpuPool,
health: NodeHealth,
dapps_domain: &str,
registrar: Arc<RegistrarClient<Call=Asynchronous>>,
registrar: Arc<ContractClient>,
sync_status: Arc<SyncStatus>,
fetch: F,
info_page_only: bool,
@@ -218,7 +217,7 @@ impl Middleware {
dapps_path: PathBuf,
extra_dapps: Vec<PathBuf>,
dapps_domain: &str,
registrar: Arc<RegistrarClient<Call=Asynchronous>>,
registrar: Arc<ContractClient>,
sync_status: Arc<SyncStatus>,
web_proxy_tokens: Arc<WebProxyTokens>,
fetch: F,

View File

@@ -19,8 +19,8 @@ use std::sync::{atomic, mpsc, Arc};
use parking_lot::Mutex;
use hyper;
use futures::{self, future, Future};
use fetch::{self, Fetch, Url, Request, Abort};
use futures::{self, Future};
use fetch::{self, Fetch, Url};
pub struct FetchControl {
sender: mpsc::Sender<()>,
@@ -34,8 +34,8 @@ impl FetchControl {
}
pub fn wait_for_requests(&self, len: usize) {
const MAX_TIMEOUT: time::Duration = time::Duration::from_millis(5000);
const ATTEMPTS: u32 = 10;
const MAX_TIMEOUT_MS: u64 = 5000;
const ATTEMPTS: u64 = 10;
let mut attempts_left = ATTEMPTS;
loop {
let current = self.fetch.requested.lock().len();
@@ -50,7 +50,7 @@ impl FetchControl {
} else {
attempts_left -= 1;
// Should we handle spurious timeouts better?
thread::park_timeout(MAX_TIMEOUT / ATTEMPTS);
thread::park_timeout(time::Duration::from_millis(MAX_TIMEOUT_MS / ATTEMPTS));
}
}
}
@@ -97,9 +97,9 @@ impl FakeFetch {
impl Fetch for FakeFetch {
type Result = Box<Future<Item = fetch::Response, Error = fetch::Error> + Send>;
fn fetch(&self, request: Request, abort: fetch::Abort) -> Self::Result {
let u = request.url().clone();
self.requested.lock().push(u.as_str().into());
fn fetch(&self, url: &str, abort: fetch::Abort) -> Self::Result {
let u = Url::parse(url).unwrap();
self.requested.lock().push(url.into());
let manual = self.manual.clone();
let response = self.response.clone();
@@ -115,20 +115,4 @@ impl Fetch for FakeFetch {
Box::new(rx.map_err(|_| fetch::Error::Aborted))
}
fn get(&self, url: &str, abort: Abort) -> Self::Result {
let url: Url = match url.parse() {
Ok(u) => u,
Err(e) => return Box::new(future::err(e.into()))
};
self.fetch(Request::get(url), abort)
}
fn post(&self, url: &str, abort: Abort) -> Self::Result {
let url: Url = match url.parse() {
Ok(u) => u,
Err(e) => return Box::new(future::err(e.into()))
};
self.fetch(Request::post(url), abort)
}
}

View File

@@ -24,7 +24,7 @@ use jsonrpc_http_server::{self as http, Host, DomainsValidation};
use parity_reactor::Remote;
use devtools::http_client;
use registrar::{RegistrarClient, Asynchronous};
use hash_fetch::urlhint::ContractClient;
use fetch::{Fetch, Client as FetchClient};
use node_health::{NodeHealth, TimeChecker, CpuPool};
@@ -144,7 +144,7 @@ pub fn assert_security_headers_for_embed(headers: &[String]) {
/// Webapps HTTP+RPC server build.
pub struct ServerBuilder<T: Fetch = FetchClient> {
dapps_path: PathBuf,
registrar: Arc<RegistrarClient<Call=Asynchronous>>,
registrar: Arc<ContractClient>,
sync_status: Arc<SyncStatus>,
web_proxy_tokens: Arc<WebProxyTokens>,
signer_address: Option<(String, u16)>,
@@ -155,7 +155,7 @@ pub struct ServerBuilder<T: Fetch = FetchClient> {
impl ServerBuilder {
/// Construct new dapps server
pub fn new<P: AsRef<Path>>(fetch: FetchClient, dapps_path: P, registrar: Arc<RegistrarClient<Call=Asynchronous>>) -> Self {
pub fn new<P: AsRef<Path>>(fetch: FetchClient, dapps_path: P, registrar: Arc<ContractClient>) -> Self {
ServerBuilder {
dapps_path: dapps_path.as_ref().to_owned(),
registrar: registrar,
@@ -219,7 +219,7 @@ impl Server {
signer_address: Option<(String, u16)>,
dapps_path: PathBuf,
extra_dapps: Vec<PathBuf>,
registrar: Arc<RegistrarClient<Call=Asynchronous>>,
registrar: Arc<ContractClient>,
sync_status: Arc<SyncStatus>,
web_proxy_tokens: Arc<WebProxyTokens>,
remote: Remote,

View File

@@ -18,9 +18,10 @@ use std::str;
use std::sync::Arc;
use std::collections::HashMap;
use futures::Future;
use ethereum_types::{H256, Address};
use bytes::{Bytes, ToPretty};
use registrar::{RegistrarClient, Asynchronous};
use hash_fetch::urlhint::ContractClient;
use parking_lot::Mutex;
use rustc_hex::FromHex;
@@ -55,20 +56,18 @@ impl FakeRegistrar {
pub fn set_result(&self, hash: H256, result: Result<Bytes, String>) {
self.responses.lock().insert(
(URLHINT.into(), format!("{}{:x}", URLHINT_RESOLVE, hash)),
(URLHINT.into(), format!("{}{:?}", URLHINT_RESOLVE, hash)),
result
);
}
}
impl RegistrarClient for FakeRegistrar {
type Call = Asynchronous;
fn registrar_address(&self) -> Result<Address, String> {
impl ContractClient for FakeRegistrar {
fn registrar(&self) -> Result<Address, String> {
Ok(REGISTRAR.parse().unwrap())
}
fn call_contract(&self, address: Address, data: Bytes) -> Self::Call {
fn call(&self, address: Address, data: Bytes) -> Box<Future<Item = Bytes, Error = String> + Send> {
let call = (address.to_hex(), data.to_hex());
self.calls.lock().push(call.clone());
let res = self.responses.lock().get(&call).cloned().expect(&format!("No response for call: {:?}", call));

View File

@@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width">
<title>Parity</title>
<style>
/* Copyright 2015-2018 Parity Technologies (UK) Ltd.
/* Copyright 2015-2017 Parity Technologies (UK) Ltd.
/* This file is part of Parity.
/*
/* Parity is free software: you can redistribute it and/or modify
@@ -107,8 +107,8 @@
<div class="parity-navbar">
</div>
<div class="parity-box">
<h1>The Parity UI has been split off into a standalone project.</h1>
<h3>Get the standalone Parity UI from <a href="https://github.com/Parity-JS/shell/releases">here</a></h3>
<h1>Parity browser UI is deprecated.</h1>
<h3>Get a standalone Parity UI from <a href="https://github.com/Parity-JS/shell/releases">here</a></h3>
<p>
</p>

View File

@@ -3,7 +3,7 @@ description = "Ethcore Parity UI"
homepage = "http://parity.io"
license = "GPL-3.0"
name = "parity-ui"
version = "1.11.0"
version = "1.9.0"
authors = ["Parity Technologies <admin@parity.io>"]
[build-dependencies]

View File

@@ -3,5 +3,5 @@ description = "Ethcore development/test/build tools"
homepage = "http://parity.io"
license = "GPL-3.0"
name = "ethcore-devtools"
version = "1.11.0"
version = "1.9.0"
authors = ["Parity Technologies <admin@parity.io>"]

View File

@@ -1,77 +0,0 @@
FROM ubuntu:xenial
LABEL maintainer="Parity Technologies <devops@parity.io>"
RUN apt-get update && \
apt-get install -yq sudo curl file build-essential wget git g++ cmake pkg-config bison flex \
unzip lib32stdc++6 lib32z1 python autotools-dev automake autoconf libtool \
gperf xsltproc docbook-xsl
# Rust & Cargo
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y
ENV PATH /root/.cargo/bin:$PATH
RUN rustup toolchain install stable
RUN rustup target add --toolchain stable arm-linux-androideabi
RUN rustup target add --toolchain stable armv7-linux-androideabi
# Android NDK and toolchain
RUN cd /usr/local && \
wget -q https://dl.google.com/android/repository/android-ndk-r16b-linux-x86_64.zip && \
unzip -q android-ndk-r16b-linux-x86_64.zip && \
rm android-ndk-r16b-linux-x86_64.zip
ENV NDK_HOME /usr/local/android-ndk-r16b
RUN /usr/local/android-ndk-r16b/build/tools/make-standalone-toolchain.sh \
--arch=arm --install-dir=/opt/ndk-standalone --stl=libc++ --platform=android-26
ENV PATH $PATH:/opt/ndk-standalone/bin
# Compiling OpenSSL for Android
RUN cd /root && \
git clone git://git.openssl.org/openssl.git && \
cd openssl && \
git checkout OpenSSL_1_1_0-stable
ENV CROSS_SYSROOT /opt/ndk-standalone/sysroot
RUN cd /root/openssl && \
./Configure android-armeabi --cross-compile-prefix=arm-linux-androideabi- \
-static no-stdio no-ui \
-I/usr/local/android-ndk-r16b/sysroot/usr/include \
-I/usr/local/android-ndk-r16b/sysroot/usr/include/arm-linux-androideabi \
-L/usr/local/android-ndk-r16b/sysroot/usr/lib \
--prefix=/opt/ndk-standalone/sysroot/usr
RUN cd /root/openssl && \
make build_libs && \
make install_dev
RUN rm -rf /root/openssl
# Compiling libudev for Android
# This is the most hacky part of the process, as we need to apply a patch and pass specific
# options that the compiler environment doesn't define.
RUN cd /root && \
git clone https://github.com/gentoo/eudev.git
ADD libudev.patch /root
RUN cd /root/eudev && \
git checkout 83d918449f22720d84a341a05e24b6d109e6d3ae && \
./autogen.sh && \
./configure --disable-introspection --disable-programs --disable-hwdb \
--host=arm-linux-androideabi --prefix=/opt/ndk-standalone/sysroot/usr/ \
--enable-shared=false CC=arm-linux-androideabi-clang \
CFLAGS="-D LINE_MAX=2048 -D RLIMIT_NLIMITS=15 -D IPTOS_LOWCOST=2 -std=gnu99" \
CXX=arm-linux-androideabi-clang++ && \
git apply - < /root/libudev.patch && \
make && \
make install
RUN rm -rf /root/eudev
RUN rm /root/libudev.patch
# Rust-related configuration
ADD cargo-config.toml /root/.cargo/config
ENV ARM_LINUX_ANDROIDEABI_OPENSSL_DIR /opt/ndk-standalone/sysroot/usr
ENV ARMV7_LINUX_ANDROIDEABI_OPENSSL_DIR /opt/ndk-standalone/sysroot/usr
ENV CC_arm_linux_androideabi arm-linux-androideabi-clang
ENV CC_armv7_linux_androideabi arm-linux-androideabi-clang
ENV CXX_arm_linux_androideabi arm-linux-androideabi-clang++
ENV CXX_armv7_linux_androideabi arm-linux-androideabi-clang++
ENV AR_arm_linux_androideabi arm-linux-androideabi-ar
ENV AR_armv7_linux_androideabi arm-linux-androideabi-ar
ENV CFLAGS_arm_linux_androideabi -std=gnu11 -fPIC -D OS_ANDROID
ENV CFLAGS_armv7_linux_androideabi -std=gnu11 -fPIC -D OS_ANDROID
ENV CXXFLAGS_arm_linux_androideabi -std=gnu++11 -fPIC -fexceptions -frtti -static-libstdc++ -D OS_ANDROID
ENV CXXFLAGS_armv7_linux_androideabi -std=gnu++11 -fPIC -fexceptions -frtti -static-libstdc++ -D OS_ANDROID

View File

@@ -1,9 +0,0 @@
[target.armv7-linux-androideabi]
linker = "arm-linux-androideabi-clang"
ar = "arm-linux-androideabi-ar"
rustflags = ["-C", "link-arg=-lc++_static", "-C", "link-arg=-lc++abi", "-C", "link-arg=-landroid_support"]
[target.arm-linux-androideabi]
linker = "arm-linux-androideabi-clang"
ar = "arm-linux-androideabi-ar"
rustflags = ["-C", "link-arg=-lc++_static", "-C", "link-arg=-lc++abi", "-C", "link-arg=-landroid_support"]

View File

@@ -1,216 +0,0 @@
diff --git a/src/collect/collect.c b/src/collect/collect.c
index 2cf1f00..b24f26b 100644
--- a/src/collect/collect.c
+++ b/src/collect/collect.c
@@ -84,7 +84,7 @@ static void usage(void)
" invoked for each ID in <idlist>) collect returns 0, the\n"
" number of missing IDs otherwise.\n"
" On error a negative number is returned.\n\n"
- , program_invocation_short_name);
+ , "parity");
}
/*
diff --git a/src/scsi_id/scsi_id.c b/src/scsi_id/scsi_id.c
index 8b76d87..7bf3948 100644
--- a/src/scsi_id/scsi_id.c
+++ b/src/scsi_id/scsi_id.c
@@ -321,7 +321,7 @@ static void help(void) {
" -u --replace-whitespace Replace all whitespace by underscores\n"
" -v --verbose Verbose logging\n"
" -x --export Print values as environment keys\n"
- , program_invocation_short_name);
+ , "parity");
}
diff --git a/src/shared/hashmap.h b/src/shared/hashmap.h
index a03ee58..a7c2005 100644
--- a/src/shared/hashmap.h
+++ b/src/shared/hashmap.h
@@ -98,10 +98,7 @@ extern const struct hash_ops uint64_hash_ops;
#if SIZEOF_DEV_T != 8
unsigned long devt_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) _pure_;
int devt_compare_func(const void *a, const void *b) _pure_;
-extern const struct hash_ops devt_hash_ops = {
- .hash = devt_hash_func,
- .compare = devt_compare_func
-};
+extern const struct hash_ops devt_hash_ops;
#else
#define devt_hash_func uint64_hash_func
#define devt_compare_func uint64_compare_func
diff --git a/src/shared/log.c b/src/shared/log.c
index 4a40996..1496984 100644
--- a/src/shared/log.c
+++ b/src/shared/log.c
@@ -335,7 +335,7 @@ static int write_to_syslog(
IOVEC_SET_STRING(iovec[0], header_priority);
IOVEC_SET_STRING(iovec[1], header_time);
- IOVEC_SET_STRING(iovec[2], program_invocation_short_name);
+ IOVEC_SET_STRING(iovec[2], "parity");
IOVEC_SET_STRING(iovec[3], header_pid);
IOVEC_SET_STRING(iovec[4], buffer);
@@ -383,7 +383,7 @@ static int write_to_kmsg(
char_array_0(header_pid);
IOVEC_SET_STRING(iovec[0], header_priority);
- IOVEC_SET_STRING(iovec[1], program_invocation_short_name);
+ IOVEC_SET_STRING(iovec[1], "parity");
IOVEC_SET_STRING(iovec[2], header_pid);
IOVEC_SET_STRING(iovec[3], buffer);
IOVEC_SET_STRING(iovec[4], "\n");
diff --git a/src/udev/udevadm-control.c b/src/udev/udevadm-control.c
index 6af7163..3271e56 100644
--- a/src/udev/udevadm-control.c
+++ b/src/udev/udevadm-control.c
@@ -41,7 +41,7 @@ static void print_help(void) {
" -p --property=KEY=VALUE Set a global property for all events\n"
" -m --children-max=N Maximum number of children\n"
" --timeout=SECONDS Maximum time to block for a reply\n"
- , program_invocation_short_name);
+ , "parity");
}
static int adm_control(struct udev *udev, int argc, char *argv[]) {
diff --git a/src/udev/udevadm-info.c b/src/udev/udevadm-info.c
index 0aec976..a31ac02 100644
--- a/src/udev/udevadm-info.c
+++ b/src/udev/udevadm-info.c
@@ -279,7 +279,7 @@ static void help(void) {
" -P --export-prefix Export the key name with a prefix\n"
" -e --export-db Export the content of the udev database\n"
" -c --cleanup-db Clean up the udev database\n"
- , program_invocation_short_name);
+ , "parity");
}
static int uinfo(struct udev *udev, int argc, char *argv[]) {
diff --git a/src/udev/udevadm-monitor.c b/src/udev/udevadm-monitor.c
index 15ded09..b58dd08 100644
--- a/src/udev/udevadm-monitor.c
+++ b/src/udev/udevadm-monitor.c
@@ -73,7 +73,7 @@ static void help(void) {
" -u --udev Print udev events\n"
" -s --subsystem-match=SUBSYSTEM[/DEVTYPE] Filter events by subsystem\n"
" -t --tag-match=TAG Filter events by tag\n"
- , program_invocation_short_name);
+ , "parity");
}
static int adm_monitor(struct udev *udev, int argc, char *argv[]) {
diff --git a/src/udev/udevadm-settle.c b/src/udev/udevadm-settle.c
index 33597bc..b36a504 100644
--- a/src/udev/udevadm-settle.c
+++ b/src/udev/udevadm-settle.c
@@ -43,7 +43,7 @@ static void help(void) {
" --version Show package version\n"
" -t --timeout=SECONDS Maximum time to wait for events\n"
" -E --exit-if-exists=FILE Stop waiting if file exists\n"
- , program_invocation_short_name);
+ , "parity");
}
static int adm_settle(struct udev *udev, int argc, char *argv[]) {
diff --git a/src/udev/udevadm-test-builtin.c b/src/udev/udevadm-test-builtin.c
index baaeca9..50ed812 100644
--- a/src/udev/udevadm-test-builtin.c
+++ b/src/udev/udevadm-test-builtin.c
@@ -39,7 +39,7 @@ static void help(struct udev *udev) {
" -h --help Print this message\n"
" --version Print version of the program\n\n"
"Commands:\n"
- , program_invocation_short_name);
+ , "parity");
udev_builtin_list(udev);
}
diff --git a/src/udev/udevadm-test.c b/src/udev/udevadm-test.c
index 47fd924..a855412 100644
--- a/src/udev/udevadm-test.c
+++ b/src/udev/udevadm-test.c
@@ -39,7 +39,7 @@ static void help(void) {
" --version Show package version\n"
" -a --action=ACTION Set action string\n"
" -N --resolve-names=early|late|never When to resolve names\n"
- , program_invocation_short_name);
+ , "parity");
}
static int adm_test(struct udev *udev, int argc, char *argv[]) {
diff --git a/src/udev/udevadm-trigger.c b/src/udev/udevadm-trigger.c
index 4dc756a..67787d3 100644
--- a/src/udev/udevadm-trigger.c
+++ b/src/udev/udevadm-trigger.c
@@ -92,7 +92,7 @@ static void help(void) {
" -y --sysname-match=NAME Trigger devices with this /sys path\n"
" --name-match=NAME Trigger devices with this /dev name\n"
" -b --parent-match=NAME Trigger devices with that parent device\n"
- , program_invocation_short_name);
+ , "parity");
}
static int adm_trigger(struct udev *udev, int argc, char *argv[]) {
diff --git a/src/udev/udevadm.c b/src/udev/udevadm.c
index 3e57cf6..b03dfaa 100644
--- a/src/udev/udevadm.c
+++ b/src/udev/udevadm.c
@@ -62,7 +62,7 @@ static int adm_help(struct udev *udev, int argc, char *argv[]) {
printf("%s [--help] [--version] [--debug] COMMAND [COMMAND OPTIONS]\n\n"
"Send control commands or test the device manager.\n\n"
"Commands:\n"
- , program_invocation_short_name);
+ , "parity");
for (i = 0; i < ELEMENTSOF(udevadm_cmds); i++)
if (udevadm_cmds[i]->help != NULL)
@@ -128,7 +128,7 @@ int main(int argc, char *argv[]) {
goto out;
}
- fprintf(stderr, "%s: missing or unknown command\n", program_invocation_short_name);
+ fprintf(stderr, "%s: missing or unknown command\n", "parity");
rc = 2;
out:
mac_selinux_finish();
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index cf826c6..4eec0af 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -1041,7 +1041,7 @@ static void help(void) {
" -t --event-timeout=SECONDS Seconds to wait before terminating an event\n"
" -N --resolve-names=early|late|never\n"
" When to resolve users and groups\n"
- , program_invocation_short_name);
+ , "parity");
}
static int parse_argv(int argc, char *argv[]) {
diff --git a/src/v4l_id/v4l_id.c b/src/v4l_id/v4l_id.c
index 1dce0d5..f65badf 100644
--- a/src/v4l_id/v4l_id.c
+++ b/src/v4l_id/v4l_id.c
@@ -49,7 +49,7 @@ int main(int argc, char *argv[]) {
printf("%s [-h,--help] <device file>\n\n"
"Video4Linux device identification.\n\n"
" -h Print this message\n"
- , program_invocation_short_name);
+ , "parity");
return 0;
case '?':
return -EINVAL;
diff --git a/src/shared/path-util.c b/src/shared/path-util.c
index 0744563..7151356 100644
--- a/src/shared/path-util.c
+++ b/src/shared/path-util.c
@@ -109,7 +109,7 @@ char *path_make_absolute_cwd(const char *p) {
if (path_is_absolute(p))
return strdup(p);
- cwd = get_current_dir_name();
+ cwd = getcwd(malloc(128), 128);
if (!cwd)
return NULL;

View File

@@ -27,7 +27,20 @@ RUN apt-get update && \
libudev-dev \
pkg-config \
dpkg-dev \
# evmjit dependencies
zlib1g-dev \
libedit-dev \
libudev-dev &&\
# cmake and llvm ppa's. then update ppa's
add-apt-repository -y "ppa:george-edison55/cmake-3.x" && \
add-apt-repository "deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.7 main" && \
apt-get update && \
apt-get install -y --force-yes cmake llvm-3.7-dev && \
# install evmjit
git clone https://github.com/debris/evmjit && \
cd evmjit && \
mkdir build && cd build && \
cmake .. && make && make install && cd && \
# install rustup
curl https://sh.rustup.rs -sSf | sh -s -- -y && \
# rustup directory
@@ -59,7 +72,11 @@ cd /build&&git clone https://github.com/paritytech/parity && \
binutils \
file \
pkg-config \
dpkg-dev &&\
dpkg-dev \
# evmjit dependencies
zlib1g-dev \
libedit-dev \
cmake llvm-3.7-dev&&\
rm -rf /var/lib/apt/lists/*
# setup ENTRYPOINT
EXPOSE 8080 8545 8180

View File

@@ -0,0 +1,58 @@
FROM ubuntu:14.04
WORKDIR /build
# install tools and dependencies
RUN apt-get update && \
apt-get install -y \
# make
build-essential \
# add-apt-repository
software-properties-common \
curl \
wget \
git \
g++ \
binutils \
file \
# evmjit dependencies
zlib1g-dev \
libedit-dev
# cmake and llvm ppas. then update ppas
RUN add-apt-repository -y "ppa:george-edison55/cmake-3.x" && \
add-apt-repository "deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.7 main" && \
apt-get update && \
apt-get install -y --force-yes cmake llvm-3.7-dev
# install evmjit
RUN git clone https://github.com/debris/evmjit && \
cd evmjit && \
mkdir build && cd build && \
cmake .. && make && make install && cd
# install rustup
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y
# rustup directory
ENV PATH /root/.cargo/bin:$PATH
# show backtraces
ENV RUST_BACKTRACE 1
# show tools
RUN rustc -vV && \
cargo -V && \
gcc -v &&\
g++ -v
# build parity
ADD . /build/parity
RUN cd parity && \
cargo build --release --features ethcore/jit --verbose && \
ls /build/parity/target/release/parity && \
strip /build/parity/target/release/parity
RUN file /build/parity/target/release/parity
EXPOSE 8080 8545 8180
ENTRYPOINT ["/build/parity/target/release/parity"]

View File

@@ -1,18 +1,3 @@
Note: Parity 1.8 reached End-of-Life on 2018-03-22 (EOL).
## Parity [v1.8.11](https://github.com/paritytech/parity/releases/tag/v1.8.11) (2018-03-01)
Parity 1.8.11 is a bug-fix release to improve performance and stability.
The full list of included changes:
- Bump stable to 1.8.11 ([#8010](https://github.com/paritytech/parity/pull/8010))
- Stable Backports ([#8008](https://github.com/paritytech/parity/pull/8008))
- Reject too large packets in snapshot sync. ([#7977](https://github.com/paritytech/parity/pull/7977))
- Increase max download limit to 128MB ([#7965](https://github.com/paritytech/parity/pull/7965))
- Calculate proper keccak256/sha3 using parity. ([#7953](https://github.com/paritytech/parity/pull/7953))
- Bump WebSockets ([#7952](https://github.com/paritytech/parity/pull/7952))
## Parity [v1.8.10](https://github.com/paritytech/parity/releases/tag/v1.8.10) (2018-02-20)
Parity 1.8.10 is a bug-fix release to improve performance and stability.

View File

@@ -1,531 +0,0 @@
## Parity [v1.9.7](https://github.com/paritytech/parity/releases/tag/v1.9.7) (2018-04-23)
Parity 1.9.7 is a bug-fix release to improve performance and stability.
The full list of included changes:
- Update Parity stable to 1.9.7 + Backports ([#8456](https://github.com/paritytech/parity/pull/8456))
- Update Parity stable to 1.9.7
- Allow 32-bit pipelines to fail ([#8454](https://github.com/paritytech/parity/pull/8454))
- Disable 32-bit targets for Gitlab
- Rename Linux pipelines
- Update wasmi ([#8452](https://github.com/paritytech/parity/pull/8452))
- Revert Cargo lock update from master
- Fix Cargo.lock
- Backports ([#8449](https://github.com/paritytech/parity/pull/8449))
- Use forked app_dirs crate for reverted Windows dir behavior ([#8438](https://github.com/paritytech/parity/pull/8438))
- Remove unused app_dirs dependency in CLI
- Use forked app_dirs crate for reverted Windows dir behavior
- Remove Tendermint extra_info due to seal inconsistencies ([#8367](https://github.com/paritytech/parity/pull/8367))
- Improve VM executor stack size estimation rules ([#8439](https://github.com/paritytech/parity/pull/8439))
- Improve VM executor stack size estimation rules
- Typo: docs add "(Debug build)" comment
- Fix an off by one typo and set minimal stack size
- Use saturating_sub to avoid potential overflow
- Upgrade crossbeam to 0.3
## Parity [v1.9.6](https://github.com/paritytech/parity/releases/tag/v1.9.6) (2018-04-16)
Parity 1.9.6 is a bug-fix release to improve performance and stability.
The full list of included changes:
- Bump app_dirs, fixes [#8315](https://github.com/paritytech/parity/issues/8315) ([#8355](https://github.com/paritytech/parity/pull/8355))
- Fix Cargo lock
- Backports ([#8352](https://github.com/paritytech/parity/pull/8352))
- Update musicoin spec in line with gmc v2.6.2 ([#8242](https://github.com/paritytech/parity/pull/8242))
- Supress TemporaryInvalid verification failures. ([#8256](https://github.com/paritytech/parity/pull/8256))
- Include suicided accounts in state diff ([#8297](https://github.com/paritytech/parity/pull/8297))
- Include suicided accounts in state diff
- Shorten form match -> if let
- Test suicide trace diff in State
- Replace_home for password_files, reserved_peers and log_file ([#8324](https://github.com/paritytech/parity/pull/8324))
- Replace_home for password_files, reserved_peers and log_file
- Typo: arg_log_file is Option
- Bump version in util/version
- Bump stable to 1.9.6 ([#8348](https://github.com/paritytech/parity/pull/8348))
- WASM libraries bump ([#8219](https://github.com/paritytech/parity/pull/8219))
- Bump wasm libs ([#8171](https://github.com/paritytech/parity/pull/8171))
- Bump wasmi version ([#8209](https://github.com/paritytech/parity/pull/8209))
- Updated jsonrpc to include latest backports (1.9) ([#8182](https://github.com/paritytech/parity/pull/8182))
- Updated jsonrpc to include latest backports (1.9)
- Update dependencies.
## Parity [v1.9.5](https://github.com/paritytech/parity/releases/tag/v1.9.5) (2018-03-21)
Parity 1.9.5 is a bug-fix release to improve performance and stability. This release marks the 1.9 track _stable_.
We are excited to announce support for **Wasm Smart Contracts on Kovan network**. The hard-fork to activate the Wasm-VM will take place on block `6600000`.
The full list of included changes:
- Do a meaningful commit that does not contain the words "ci" or "skip"
- Triggering build for stable.
- Postpone Kovan hard fork ([#8137](https://github.com/paritytech/parity/pull/8137)) ([#8152](https://github.com/paritytech/parity/pull/8152))
- Postpone Kovan hard fork ([#8137](https://github.com/paritytech/parity/pull/8137))
- ethcore: postpone Kovan hard fork
- util: update version fork metadata
- WASM libraries bump ([#7970](https://github.com/paritytech/parity/pull/7970))
- update wasmi, parity-wasm, wasm-utils to latest version
- Update to new wasmi & error handling
- also utilize new stack limiter
- fix typo
- replace dependency url
- Cargo.lock update
- Fix scripts. Force JS rebuild. ([#8144](https://github.com/paritytech/parity/pull/8144))
- Stable Backports ([#8133](https://github.com/paritytech/parity/pull/8133))
- updater: apply exponential backoff after download failure ([#8059](https://github.com/paritytech/parity/pull/8059))
- updater: apply exponential backoff after download failure
- updater: reset backoff on new release
- Limit incoming connections. ([#8060](https://github.com/paritytech/parity/pull/8060))
- Limit ingress connections
- Optimized handshakes logging
- Max code size on Kovan ([#8067](https://github.com/paritytech/parity/pull/8067))
- Enable code size limit on kovan
- Fix formatting.
- add some dos protection ([#8084](https://github.com/paritytech/parity/pull/8084))
- more dos protection ([#8104](https://github.com/paritytech/parity/pull/8104))
- Const time comparison ([#8113](https://github.com/paritytech/parity/pull/8113))
- Use `subtle::slices_equal` for constant time comparison.
- Also update the existing version of subtle in `ethcrypto` from
- 0.1 to 0.5
- Test specifically for InvalidPassword error.
- revert removing blooms ([#8066](https://github.com/paritytech/parity/pull/8066))
- Revert "fix traces, removed bloomchain crate, closes [#7228](https://github.com/paritytech/parity/pull/7228), closes [#7167](https://github.com/paritytech/parity/pull/7167)"
- Revert "fixed broken logs ([#7934](https://github.com/paritytech/parity/pull/7934))"
- fixed broken logs
- bring back old lock order
- remove migration v13
- revert CURRENT_VERSION to 12 in migration.rs
- Fix compilation.
- Check one step deeper if we're on release track branches
- add missing pr
- Fix blooms?
- Fix tests compiilation.
- Fix size.
- Check one step deeper if we're on release track branches ([#8134](https://github.com/paritytech/parity/pull/8134)) ([#8140](https://github.com/paritytech/parity/pull/8140))
- Trigger js build. ([#8121](https://github.com/paritytech/parity/pull/8121))
- Stable backports ([#8055](https://github.com/paritytech/parity/pull/8055))
- CI: Fix cargo cache ([#7968](https://github.com/paritytech/parity/pull/7968))
- Fix cache
Blocking waiting for file lock on the registry index
- Only clean locked cargo cache on windows
- fixed ethstore sign ([#8026](https://github.com/paritytech/parity/pull/8026))
- fix cache & snapcraft CI build ([#8052](https://github.com/paritytech/parity/pull/8052))
- Add MCIP-6 Byzyantium transition to Musicoin spec ([#7841](https://github.com/paritytech/parity/pull/7841))
- Add test chain spec for musicoin byzantium testnet
- Add MCIP-6 Byzyantium transition to Musicoin spec
- Update mcip6_byz.json
- ethcore: update musicoin byzantium block number
- ethcore: update musicoin bootnodes
- Update musicoin.json
- More bootnodes.
- Optimize JS build ([#8093](https://github.com/paritytech/parity/pull/8093))
- Extract common chunks plugin.
- Fix common CSS.
- Fix js push for stable.
- Remove arguments to getPlugins.
- Stable Backports ([#8058](https://github.com/paritytech/parity/pull/8058))
- fixed parsing ethash seals and verify_block_undordered ([#8031](https://github.com/paritytech/parity/pull/8031))
- fix for verify_block_basic crashing on invalid transaction rlp ([#8032](https://github.com/paritytech/parity/pull/8032))
- Make 1.9 stable ([#8023](https://github.com/paritytech/parity/pull/8023))
- Make 1.9 stable
- Bump stable to 1.9.5
- Fix gitlab builds
## Parity [v1.9.4](https://github.com/paritytech/parity/releases/tag/v1.9.4) (2018-03-01)
Parity 1.9.4 is a bug-fix release to improve performance and stability.
The full list of included changes:
- Bump beta to 1.9.4 ([#8016](https://github.com/paritytech/parity/pull/8016))
- Beta Backports ([#8011](https://github.com/paritytech/parity/pull/8011))
- Fix traces, removed bloomchain crate ([#7979](https://github.com/paritytech/parity/pull/7979))
- Reject too large packets in snapshot sync. ([#7977](https://github.com/paritytech/parity/pull/7977))
- Fixed broken logs ([#7934](https://github.com/paritytech/parity/pull/7934))
- Increase max download limit to 128MB ([#7965](https://github.com/paritytech/parity/pull/7965))
- Calculate proper keccak256/sha3 using parity. ([#7953](https://github.com/paritytech/parity/pull/7953))
- Bump WebSockets ([#7952](https://github.com/paritytech/parity/pull/7952))
- Hardware-wallet/usb-subscribe-refactor ([#7860](https://github.com/paritytech/parity/pull/7860))
- Make block generator easier to use ([#7888](https://github.com/paritytech/parity/pull/7888))
## Parity [v1.9.3](https://github.com/paritytech/parity/releases/tag/v1.9.3) (2018-02-20)
Parity 1.9.3 is a bug-fix release to improve performance and stability.
The full list of included changes:
- Backports ([#7945](https://github.com/paritytech/parity/pull/7945))
- ECIP 1041 - Remove Difficulty Bomb ([#7905](https://github.com/paritytech/parity/pull/7905))
- spec: Validate required divisor fields are not 0 ([#7933](https://github.com/paritytech/parity/pull/7933))
- Kovan WASM fork code ([#7849](https://github.com/paritytech/parity/pull/7849))
- Gitlab Cargo Cache ([#7944](https://github.com/paritytech/parity/pull/7944))
- Bump react-qr-reader ([#7943](https://github.com/paritytech/parity/pull/7943))
- Update react-qr-reader
- Explicit webrtc-adapter dependency (package-lock workaround)
- Iframe with allow (QR, new Chrome policy)
- Backport of [#7844](https://github.com/paritytech/parity/pull/7844) and [#7917](https://github.com/paritytech/parity/pull/7917) to beta ([#7940](https://github.com/paritytech/parity/pull/7940))
- Randomize the peer we dispatch to
- Fix a division by zero in light client RPC handler
- Wallet allowJsEval: true ([#7913](https://github.com/paritytech/parity/pull/7913))
- Wallet allowJsEval: true
- Fix unsafe wallet.
- Enable unsafe-eval for all dapps.
- Fix CSP for dapps that require eval. ([#7867](https://github.com/paritytech/parity/pull/7867)) ([#7903](https://github.com/paritytech/parity/pull/7903))
- Add allowJsEval to manifest.
- Enable 'unsafe-eval' if requested in manifest.
- Fix snap build beta ([#7895](https://github.com/paritytech/parity/pull/7895))
- Fix snapcraft grade to stable ([#7894](https://github.com/paritytech/parity/pull/7894))
- Backport Master CI PRs to Beta ([#7890](https://github.com/paritytech/parity/pull/7890))
- Add binary identifiers and sha256sum to builds ([#7830](https://github.com/paritytech/parity/pull/7830))
- Fix checksums and auto-update push ([#7846](https://github.com/paritytech/parity/pull/7846))
- Update gitlab-build.sh ([#7855](https://github.com/paritytech/parity/pull/7855))
- Fix installer binary names for macos and windows ([#7881](https://github.com/paritytech/parity/pull/7881))
- Update gitlab-test.sh ([#7883](https://github.com/paritytech/parity/pull/7883))
- Fix snapcraft nightly ([#7884](https://github.com/paritytech/parity/pull/7884))
- Backport Core PRs to beta ([#7891](https://github.com/paritytech/parity/pull/7891))
- Update back-references more aggressively after answering from cache ([#7578](https://github.com/paritytech/parity/pull/7578))
- Updated WASM Runtime & new interpreter (wasmi) ([#7796](https://github.com/paritytech/parity/pull/7796))
- Adjust storage update evm-style ([#7812](https://github.com/paritytech/parity/pull/7812))
- Add new EF ropstens nodes ([#7824](https://github.com/paritytech/parity/pull/7824))
- Store updater metadata in a single place ([#7832](https://github.com/paritytech/parity/pull/7832))
- WASM: Disable internal memory ([#7842](https://github.com/paritytech/parity/pull/7842))
- Add a timeout for light client sync requests ([#7848](https://github.com/paritytech/parity/pull/7848))
- Flush keyfiles. Resolves [#7632](https://github.com/paritytech/parity/issues/7632) ([#7868](https://github.com/paritytech/parity/pull/7868))
- Fix wallet import ([#7873](https://github.com/paritytech/parity/pull/7873))
## Parity [v1.9.2](https://github.com/paritytech/parity/releases/tag/v1.9.2) (2018-02-02)
Parity 1.9.2 is a bug-fix release to improve performance and stability. It adds additional bootnodes for the Ropsten test network.
The full list of included changes:
- Backports beta ([#7780](https://github.com/paritytech/parity/pull/7780))
- Bump beta to 1.9.2
- Update ropsten.json ([#7776](https://github.com/paritytech/parity/pull/7776))
- Snapcraft push beta
## Parity [v1.9.1](https://github.com/paritytech/parity/releases/tag/v1.9.1) (2018-02-01)
Parity 1.9.1 is a bug-fix release to improve performance and stability. It restores ERC-20 token balances, improves networking, fixes database corruptions on client shutdown, and fixes issues with the `--password` command-line flag. Happy syncing, fellow Ethereans!
In addition, this stabilizes Kovan and other Proof-of-Authority networks. If you run a network with AuRa engine, updating is highly encouraged!
The full list of included changes:
- Beta Backports ([#7756](https://github.com/paritytech/parity/pull/7756))
- Filter-out nodes.json ([#7716](https://github.com/paritytech/parity/pull/7716))
- Filter-out nodes.json
- network: sort node table nodes by failure ratio
- network: fix node table tests
- network: fit node failure percentage into buckets of 5%
- network: consider number of attempts in sorting of node table
- network: fix node table grumbles
- Fix client not being dropped on shutdown ([#7695](https://github.com/paritytech/parity/pull/7695))
- parity: wait for client to drop on shutdown
- parity: fix grumbles in shutdown wait
- parity: increase shutdown timeouts
- Wrap --help output to 120 characters ([#7626](https://github.com/paritytech/parity/pull/7626))
- Update Clap dependency and remove workarounds
- WIP
- Remove line breaks in help messages for now
- Multiple values can only be separated by commas (closes [#7428](https://github.com/paritytech/parity/issues/7428))
- Grumbles; refactor repeating code; add constant
- Use a single Wrapper rather than allocate a new one for each call
- Wrap --help to 120 characters rather than 100 characte
- Token filter balances (throttle) ([#7742](https://github.com/paritytech/parity/pull/7742))
- Token filter balances (throttle)
- Cleanups
- Remove unused uniq
- Update @parity/shared to 2.2.23
- Remove unused code paths
- Bump beta to 1.9.1 ([#7751](https://github.com/paritytech/parity/pull/7751))
- Explicitly add branch name ([#7754](https://github.com/paritytech/parity/pull/7754))
- Explicitly add branch name
- Fix cargo update branch to beta
- Revert revert revert ([#7715](https://github.com/paritytech/parity/pull/7715))
- This reverts commit 568dc33.
## Parity [v1.9.0](https://github.com/paritytech/parity/releases/tag/v1.9.0) "Velocity" (2018-01-25)
We are happy to announce our newest Parity 1.9 release. Among others, it enables the following features:
- It integrates the fully reworked Parity Wallet and DApps browser (a.k.a. "UI 2.0", [#6819](https://github.com/paritytech/parity/pull/6819)).
- It enables devp2p snappy compression ([#6683](https://github.com/paritytech/parity/pull/6683)).
- AuRa Proof-of-Authority chains now disable uncles by default ([#7006](https://github.com/paritytech/parity/pull/7006)). Existing PoA chains can go through a "maximum uncle count transition" to achieve more stability ([#7196](https://github.com/paritytech/parity/pull/7196)).
- Added Expanse's Byzantium hard-fork ([#7463](https://github.com/paritytech/parity/pull/7463)).
- Added support for Ellaism chain ([#7222](https://github.com/paritytech/parity/pull/7222)).
Further, users upgrading from 1.8 should acknowledge the following changes:
- Fixed DELEGATECALL's from/to field ([#7568](https://github.com/paritytech/parity/pull/7568)).
- Set zero nonce and gas price for calls by default ([#6954](https://github.com/paritytech/parity/pull/6954)).
- Create pending blocks with all transactions from the queue ([#6942](https://github.com/paritytech/parity/pull/6942)).
- Remove RPC parameter leniency now that Mist formats correctly ([#6651](https://github.com/paritytech/parity/pull/6651)). Parity stops accepting decimal-formatted block numbers and stops parsing the empty string as empty bytes.
- Public nodes do not support the user interface anymore. If you are running a public node, please stay on the 1.8 branch of the stable releases.
Additional noteworthy changes:
- `ethstore` and `ethkey` have been significantly improved ([#6961](https://github.com/paritytech/parity/pull/6961)):
- `ethstore` now supports brute forcing pre-sale wallets given a password list for recovery.
- `ethkey` now supports multi-threaded generation of prefix-matching addresses.
- `ethkey` now supports prefix-matching brain wallets.
- `ethkey` now supports brain-wallets recovery-phrases lookup. This helps to find a correct phrase if you know the address you want to get yet you made a typo backing the phrase up, or forgot a word.
Read more about Parity 1.9 in our [blog post](http://paritytech.io/velocity-the-fastest-parity-released/).
The full list of included changes:
- Add scroll when when too many accounts ([#7677](https://github.com/paritytech/parity/pull/7677)) ([#7679](https://github.com/paritytech/parity/pull/7679))
- Update installer.nsi
- Fix conditions in gitlab-test ([#7676](https://github.com/paritytech/parity/pull/7676))
- Fix conditions in gitlab-test
- Update gitlab-test.sh
- Remove cargo cache
- Backports to beta ([#7660](https://github.com/paritytech/parity/pull/7660))
- Improve handling of RocksDB corruption ([#7630](https://github.com/paritytech/parity/pull/7630))
- Kvdb-rocksdb: update rust-rocksdb version
- Kvdb-rocksdb: mark corruptions and attempt repair on db open
- Kvdb-rocksdb: better corruption detection on open
- Kvdb-rocksdb: add corruption_file_name const
- Kvdb-rocksdb: rename mark_corruption to check_for_corruption
- Hardening of CSP ([#7621](https://github.com/paritytech/parity/pull/7621))
- Fixed delegatecall's from/to ([#7568](https://github.com/paritytech/parity/pull/7568))
- Fixed delegatecall's from/to, closes [#7166](https://github.com/paritytech/parity/issues/7166)
- Added tests for delegatecall traces, [#7167](https://github.com/paritytech/parity/issues/7167)
- Light client RPCs ([#7603](https://github.com/paritytech/parity/pull/7603))
- Implement registrar.
- Implement eth_getCode
- Don't wait for providers.
- Don't wait for providers.
- Fix linting and wasm tests.
- Problem: AttachedProtocols don't get registered ([#7610](https://github.com/paritytech/parity/pull/7610))
- Fix Temporarily Invalid blocks handling ([#7613](https://github.com/paritytech/parity/pull/7613))
- Handle temporarily invalid blocks in sync.
- Fix tests.
- Add docker build for beta ([#7671](https://github.com/paritytech/parity/pull/7671))
- Add docker build for beta
- Add cargo cache
- Fix snapcraft build for beta ([#7670](https://github.com/paritytech/parity/pull/7670))
- Update Parity.pkgproj
- update gitlab build from master
- Update references to dapp sources ([#7634](https://github.com/paritytech/parity/pull/7634)) ([#7636](https://github.com/paritytech/parity/pull/7636))
- Update tokenreg ([#7618](https://github.com/paritytech/parity/pull/7618)) ([#7619](https://github.com/paritytech/parity/pull/7619))
- Fix cache:key ([#7598](https://github.com/paritytech/parity/pull/7598))
- Make 1.9 beta ([#7533](https://github.com/paritytech/parity/pull/7533))
- Trigger js-precompiled ([#7535](https://github.com/paritytech/parity/pull/7535))
- RocksDB fix ([#7512](https://github.com/paritytech/parity/pull/7512))
- Update js-api ([#7510](https://github.com/paritytech/parity/pull/7510))
- Expose default gas price percentile configuration in CLI ([#7497](https://github.com/paritytech/parity/pull/7497))
- Use https connection ([#7503](https://github.com/paritytech/parity/pull/7503))
- More thorough changes detection ([#7472](https://github.com/paritytech/parity/pull/7472))
- Fix small layout issues ([#7500](https://github.com/paritytech/parity/pull/7500))
- Show all accounts on Topbar ([#7498](https://github.com/paritytech/parity/pull/7498))
- Update Parity Mainnet Bootnodes ([#7476](https://github.com/paritytech/parity/pull/7476))
- Fixed panic when io is not available for export block ([#7495](https://github.com/paritytech/parity/pull/7495))
- Advance AuRa step as far as we can and prevent invalid blocks. ([#7451](https://github.com/paritytech/parity/pull/7451))
- Update package-lock in js-old ([#7494](https://github.com/paritytech/parity/pull/7494))
- Update issue template and readme ([#7450](https://github.com/paritytech/parity/pull/7450))
- Update package-lock.json pinned versions ([#7492](https://github.com/paritytech/parity/pull/7492))
- Explicit pre-precompiled push checkout ([#7474](https://github.com/paritytech/parity/pull/7474))
- Trigger js-precompiled ([#7473](https://github.com/paritytech/parity/pull/7473))
- Expanse Byzantium update w/ correct metropolis difficulty increment divisor ([#7463](https://github.com/paritytech/parity/pull/7463))
- Updated icons ([#7469](https://github.com/paritytech/parity/pull/7469))
- Cleanup certifications ([#7454](https://github.com/paritytech/parity/pull/7454))
- Fix css lint (updated stylelint) ([#7471](https://github.com/paritytech/parity/pull/7471))
- Upgrade markdown-loader & marked ([#7467](https://github.com/paritytech/parity/pull/7467))
- Remove JS test for removed code ([#7461](https://github.com/paritytech/parity/pull/7461))
- Pull in dapp-status ([#7457](https://github.com/paritytech/parity/pull/7457))
- Bump openssl crate ([#7455](https://github.com/paritytech/parity/pull/7455))
- Signer updates from global Redux state ([#7452](https://github.com/paritytech/parity/pull/7452))
- Remove expanse chain ([#7437](https://github.com/paritytech/parity/pull/7437))
- Store tokens with repeatable id ([#7435](https://github.com/paritytech/parity/pull/7435))
- Strict config parsing ([#7433](https://github.com/paritytech/parity/pull/7433))
- Upgrade to RocksDB 5.8.8 and tune settings to reduce space amplification ([#7348](https://github.com/paritytech/parity/pull/7348))
- Fix status layout ([#7432](https://github.com/paritytech/parity/pull/7432))
- Fix tracing failed calls. ([#7412](https://github.com/paritytech/parity/pull/7412))
- Problem: sending any Whisper message fails ([#7421](https://github.com/paritytech/parity/pull/7421))
- Wait for future blocks in AuRa ([#7368](https://github.com/paritytech/parity/pull/7368))
- Fix final feature. ([#7426](https://github.com/paritytech/parity/pull/7426))
- Use RwLock for state DB ([#7425](https://github.com/paritytech/parity/pull/7425))
- Update branding on UI ([#7370](https://github.com/paritytech/parity/pull/7370))
- Changelog for 1.8.5 and 1.7.11 ([#7401](https://github.com/paritytech/parity/pull/7401))
- Added checking tx-type using transactions permission contract for miners ([#7359](https://github.com/paritytech/parity/pull/7359))
- Standalone dir crate, replaces [#7383](https://github.com/paritytech/parity/issues/7383) ([#7409](https://github.com/paritytech/parity/pull/7409))
- SecretStore: secretstore_signRawHash method ([#7336](https://github.com/paritytech/parity/pull/7336))
- SecretStore: return error 404 when there's no key shares for given key on all nodes ([#7331](https://github.com/paritytech/parity/pull/7331))
- SecretStore: PoA integration initial version ([#7101](https://github.com/paritytech/parity/pull/7101))
- Update bootnodes ([#7363](https://github.com/paritytech/parity/pull/7363))
- Fix default CORS settings. ([#7387](https://github.com/paritytech/parity/pull/7387))
- Fix version ([#7390](https://github.com/paritytech/parity/pull/7390))
- Wasm runtime update ([#7356](https://github.com/paritytech/parity/pull/7356))
- Parity-version pr reopen ([#7136](https://github.com/paritytech/parity/pull/7136))
- Get rid of clippy remainings. ([#7355](https://github.com/paritytech/parity/pull/7355))
- Avoid using ok_or with allocated argument ([#7357](https://github.com/paritytech/parity/pull/7357))
- Make accounts refresh time configurable. ([#7345](https://github.com/paritytech/parity/pull/7345))
- Enable traces for DEV chain ([#7327](https://github.com/paritytech/parity/pull/7327))
- Problem: AuRa's unsafeties around step duration ([#7282](https://github.com/paritytech/parity/pull/7282))
- Problem: Cargo.toml file contains [project] key ([#7346](https://github.com/paritytech/parity/pull/7346))
- Fix broken flex modal layouts ([#7343](https://github.com/paritytech/parity/pull/7343))
- Fix dappIcon & Fix Signer Pending ([#7338](https://github.com/paritytech/parity/pull/7338))
- Fix wallet token/badge icons not showing up ([#7333](https://github.com/paritytech/parity/pull/7333))
- Add Ellaism coin in chain config ([#7222](https://github.com/paritytech/parity/pull/7222))
- Update bootnodes ([#7296](https://github.com/paritytech/parity/pull/7296))
- Adds `personal_signTransaction` RPC method ([#6991](https://github.com/paritytech/parity/pull/6991))
- Fix double initialization of embeded providers. ([#7326](https://github.com/paritytech/parity/pull/7326))
- Transaction Pool re-implementation ([#6994](https://github.com/paritytech/parity/pull/6994))
- UI package bump ([#7318](https://github.com/paritytech/parity/pull/7318))
- Test framework and basic test for whisper ([#7011](https://github.com/paritytech/parity/pull/7011))
- CI js-precompiled trigger ([#7316](https://github.com/paritytech/parity/pull/7316))
- Fix inject.js & Signer store duplication ([#7299](https://github.com/paritytech/parity/pull/7299))
- Detect different node, same-key signing in aura ([#7245](https://github.com/paritytech/parity/pull/7245))
- New warp enodes ([#7287](https://github.com/paritytech/parity/pull/7287))
- CSS fixes for v1 ([#7285](https://github.com/paritytech/parity/pull/7285))
- Wallet subscriptions & refresh ([#7283](https://github.com/paritytech/parity/pull/7283))
- Update inject web3 dependencies ([#7286](https://github.com/paritytech/parity/pull/7286))
- Some padding around dapp image ([#7276](https://github.com/paritytech/parity/pull/7276))
- Expand available middleware methods ([#7275](https://github.com/paritytech/parity/pull/7275))
- Inject parity script to all dapps // Expand dapps to any ZIP file ([#7260](https://github.com/paritytech/parity/pull/7260))
- New Homepage ([#7266](https://github.com/paritytech/parity/pull/7266))
- Update kovan HF block number. ([#7259](https://github.com/paritytech/parity/pull/7259))
- CHANGELOG for 1.7.10 and 1.8.4 ([#7265](https://github.com/paritytech/parity/pull/7265))
- Remove extraneous id hashing ([#7269](https://github.com/paritytech/parity/pull/7269))
- Simplify status + content display overlaps/page fixing ([#7264](https://github.com/paritytech/parity/pull/7264))
- UI redirect to 127.0.0.1 when localhost requested ([#7236](https://github.com/paritytech/parity/pull/7236))
- Usability improvements to security token Dialog [#7112](https://github.com/paritytech/parity/issues/7112) ([#7134](https://github.com/paritytech/parity/pull/7134))
- Don't display unneeded notifications ([#7237](https://github.com/paritytech/parity/pull/7237))
- Reduce max block timestamp drift to 15 seconds ([#7240](https://github.com/paritytech/parity/pull/7240))
- Increase allowed time drift to 10s. ([#7238](https://github.com/paritytech/parity/pull/7238))
- Improve building from source ([#7239](https://github.com/paritytech/parity/pull/7239))
- Fix/Update method permissions ([#7233](https://github.com/paritytech/parity/pull/7233))
- Fix aura difficulty race ([#7198](https://github.com/paritytech/parity/pull/7198))
- Dependency updates ([#7226](https://github.com/paritytech/parity/pull/7226))
- Display all dapps (shell) & wallet tabs (v1) by default ([#7213](https://github.com/paritytech/parity/pull/7213))
- Rework dapps list ([#7206](https://github.com/paritytech/parity/pull/7206))
- Add contributing guidelines and code of conduct. ([#7157](https://github.com/paritytech/parity/pull/7157))
- Make Signing Requests more visible ([#7204](https://github.com/paritytech/parity/pull/7204))
- Send each log as a separate notification ([#7175](https://github.com/paritytech/parity/pull/7175))
- Deleting a mistake comment in calc difficulty ([#7154](https://github.com/paritytech/parity/pull/7154))
- Maximum uncle count transition ([#7196](https://github.com/paritytech/parity/pull/7196))
- Update FirstRun for UI-2 ([#7195](https://github.com/paritytech/parity/pull/7195))
- Update mocha import stubs ([#7191](https://github.com/paritytech/parity/pull/7191))
- Escape inifinite loop in estimte_gas ([#7075](https://github.com/paritytech/parity/pull/7075))
- New account selector UI in top bar ([#7179](https://github.com/paritytech/parity/pull/7179))
- Removed ethcore-util dependency from ethcore-network ([#7180](https://github.com/paritytech/parity/pull/7180))
- WASM test runner utility upgrade ([#7147](https://github.com/paritytech/parity/pull/7147))
- React 16 ([#7174](https://github.com/paritytech/parity/pull/7174))
- Assorted improvements for ethstore and ethkey ([#6961](https://github.com/paritytech/parity/pull/6961))
- Delete unused package.json (dist bundles) ([#7173](https://github.com/paritytech/parity/pull/7173))
- Remove *.css.map & *.js.map ([#7168](https://github.com/paritytech/parity/pull/7168))
- Use git flag to remove old js artifacts ([#7165](https://github.com/paritytech/parity/pull/7165))
- Cleanup JS build artifacts ([#7164](https://github.com/paritytech/parity/pull/7164))
- Fixes typo in user config path ([#7159](https://github.com/paritytech/parity/pull/7159))
- Pull in new dapp-{methods,visible} dapps ([#7150](https://github.com/paritytech/parity/pull/7150))
- WASM test runner utility ([#7142](https://github.com/paritytech/parity/pull/7142))
- WASM Remove blockhash error ([#7121](https://github.com/paritytech/parity/pull/7121))
- ECIP-1039: Monetary policy rounding specification ([#7067](https://github.com/paritytech/parity/pull/7067))
- Fixed `RotatingLogger` after migrating to new arrayvec ([#7129](https://github.com/paritytech/parity/pull/7129))
- Push to correct shell branch ([#7135](https://github.com/paritytech/parity/pull/7135))
- Update js-precompiled ref, trigger JS build ([#7132](https://github.com/paritytech/parity/pull/7132))
- Fixed build && test ([#7128](https://github.com/paritytech/parity/pull/7128))
- Update packages, pull in compiled-only repos ([#7125](https://github.com/paritytech/parity/pull/7125))
- Cleanup top bar, add Home icon for navigation ([#7118](https://github.com/paritytech/parity/pull/7118))
- WASM storage_read and storage_write don't return anything ([#7110](https://github.com/paritytech/parity/pull/7110))
- Local dapp development URL ([#7100](https://github.com/paritytech/parity/pull/7100))
- Remove unused and duplicated files in js-old ([#7082](https://github.com/paritytech/parity/pull/7082))
- Optimize & group dapp requests ([#7083](https://github.com/paritytech/parity/pull/7083))
- WASM parse payload from panics ([#7097](https://github.com/paritytech/parity/pull/7097))
- Fix no-default-features. ([#7096](https://github.com/paritytech/parity/pull/7096))
- Updated eth-secp256k1 ([#7090](https://github.com/paritytech/parity/pull/7090))
- Improve Github Issue Template ([#7099](https://github.com/paritytech/parity/pull/7099))
- Changes necessary to upload crates to crates.io ([#7020](https://github.com/paritytech/parity/pull/7020))
- Reopened 6860 - iterate over both buffered and unbuffered database entries ([#7048](https://github.com/paritytech/parity/pull/7048))
- SecretStore: servers set change session api ([#6925](https://github.com/paritytech/parity/pull/6925))
- Disable uncles by default ([#7006](https://github.com/paritytech/parity/pull/7006))
- Squashed ethcore-network changes which introduce error-chain ([#7040](https://github.com/paritytech/parity/pull/7040))
- Removed redundant imports ([#7057](https://github.com/paritytech/parity/pull/7057))
- CHANGELOG for 1.7.8, 1.7.9, 1.8.2, and 1.8.3 ([#7055](https://github.com/paritytech/parity/pull/7055))
- Properly display Signer errors (Snackbar display popup) ([#7053](https://github.com/paritytech/parity/pull/7053))
- Add the desktop file for the snap ([#7059](https://github.com/paritytech/parity/pull/7059))
- Small performance gain in allocations ([#7054](https://github.com/paritytech/parity/pull/7054))
- Bump JSON-RPC version ([#7051](https://github.com/paritytech/parity/pull/7051))
- Fix nonce reservation ([#7025](https://github.com/paritytech/parity/pull/7025))
- Fixed ethstore-cli output ([#7052](https://github.com/paritytech/parity/pull/7052))
- Add mui for embed compilation ([#7049](https://github.com/paritytech/parity/pull/7049))
- Update the snap metadata to keep working strictly confined ([#6993](https://github.com/paritytech/parity/pull/6993))
- Remove unused js packages (dapp cleanups) ([#7046](https://github.com/paritytech/parity/pull/7046))
- Gitlog location update ([#7042](https://github.com/paritytech/parity/pull/7042))
- Move git logging to .git-release.log ([#7041](https://github.com/paritytech/parity/pull/7041))
- Start from rust root in release update step ([#7039](https://github.com/paritytech/parity/pull/7039))
- Complete token merge, remove unused files ([#7037](https://github.com/paritytech/parity/pull/7037))
- Add missing cargo-push.sh shell variable ([#7036](https://github.com/paritytech/parity/pull/7036))
- Fix npm start script ([#7034](https://github.com/paritytech/parity/pull/7034))
- Update executable flags on release scripts ([#7035](https://github.com/paritytech/parity/pull/7035))
- Fix v1 precompiled ([#7033](https://github.com/paritytech/parity/pull/7033))
- Push precompiled to correct branch (v1) ([#7031](https://github.com/paritytech/parity/pull/7031))
- Update v1 Wallet Dapp ([#6935](https://github.com/paritytech/parity/pull/6935))
- WASM tests update ([#7018](https://github.com/paritytech/parity/pull/7018))
- Events in WASM runtime ([#6967](https://github.com/paritytech/parity/pull/6967))
- Adds validate_node_url() and refactors boot node check ([#6907](https://github.com/paritytech/parity/pull/6907)) ([#6970](https://github.com/paritytech/parity/pull/6970))
- Fix windows build (with ui rebuild) ([#7016](https://github.com/paritytech/parity/pull/7016))
- Make CLI arguments parsing more backwards compatible ([#7004](https://github.com/paritytech/parity/pull/7004))
- Fixes for parity-extension ([#6990](https://github.com/paritytech/parity/pull/6990))
- Update ethcore-bigint ([#6992](https://github.com/paritytech/parity/pull/6992))
- Get local transactions by hash in the light client ([#6874](https://github.com/paritytech/parity/pull/6874))
- Warn when blacklisted account present in store ([#6875](https://github.com/paritytech/parity/pull/6875))
- Skip nonce check for gas estimation ([#6997](https://github.com/paritytech/parity/pull/6997))
- Creating pending block with all transactions from the queue ([#6942](https://github.com/paritytech/parity/pull/6942))
- Removes `MAX_TX_TO_IMPORT` from `ChainSync` ([#6976](https://github.com/paritytech/parity/pull/6976))
- SecretStore: versioned keys ([#6910](https://github.com/paritytech/parity/pull/6910))
- Removes `FUTURE_QUEUE_LIMITS_SHIFT` ([#6962](https://github.com/paritytech/parity/pull/6962))
- Set zero nonce and gas price for calls by default ([#6954](https://github.com/paritytech/parity/pull/6954))
- Add hint in ActionParams for splitting code/data ([#6957](https://github.com/paritytech/parity/pull/6957))
- Return decoded seal fields. ([#6932](https://github.com/paritytech/parity/pull/6932))
- Fix serialization of status in transaction receipts. ([#6926](https://github.com/paritytech/parity/pull/6926))
- Reserve nonces for signing ([#6834](https://github.com/paritytech/parity/pull/6834))
- Windows fixes ([#6921](https://github.com/paritytech/parity/pull/6921))
- Don't add {css,js}.map from dapps ([#6931](https://github.com/paritytech/parity/pull/6931))
- Fix JSON tracing for sub-calls. ([#6842](https://github.com/paritytech/parity/pull/6842))
- Shell updates (bonds, updated Dapps) ([#6897](https://github.com/paritytech/parity/pull/6897))
- Fix [#6228](https://github.com/paritytech/parity/issues/6228): do not display eth price in cli for etc ([#6877](https://github.com/paritytech/parity/pull/6877))
- Fix mining help ([#6885](https://github.com/paritytech/parity/pull/6885))
- Refactor static context check in CREATE. ([#6886](https://github.com/paritytech/parity/pull/6886))
- Cleanup some configuration options ([#6878](https://github.com/paritytech/parity/pull/6878))
- Fix serialization of non-localized transactions ([#6868](https://github.com/paritytech/parity/pull/6868))
- Updated ntp to version 0.3 ([#6854](https://github.com/paritytech/parity/pull/6854))
- Align README with 1.8 and prepare CHANGELOG with 1.8.1 ([#6833](https://github.com/paritytech/parity/pull/6833))
- Return error on timed unlock ([#6777](https://github.com/paritytech/parity/pull/6777))
- Fix dapps tests in master ([#6866](https://github.com/paritytech/parity/pull/6866))
- Ethstore optimizations ([#6827](https://github.com/paritytech/parity/pull/6827))
- Add ECIP1017 to Morden config ([#6810](https://github.com/paritytech/parity/pull/6810))
- Remove all package publishing to npm ([#6838](https://github.com/paritytech/parity/pull/6838))
- Util crates use tempdir crate instead of devtools to create temp path ([#6807](https://github.com/paritytech/parity/pull/6807))
- Trigger js build ([#6836](https://github.com/paritytech/parity/pull/6836))
- Clean-up scripts. ([#6832](https://github.com/paritytech/parity/pull/6832))
- Tweaked snapshot sync threshold ([#6829](https://github.com/paritytech/parity/pull/6829))
- Integrate UI 2 ([#6819](https://github.com/paritytech/parity/pull/6819))
- Refresh cached tokens based on registry info & random balances ([#6818](https://github.com/paritytech/parity/pull/6818))
- Change keypath derivation logic ([#6815](https://github.com/paritytech/parity/pull/6815))
- Refactors journaldb as a separate crate ([#6801](https://github.com/paritytech/parity/pull/6801))
- Trigger UI build. ([#6817](https://github.com/paritytech/parity/pull/6817))
- Bumped more crate versions ([#6809](https://github.com/paritytech/parity/pull/6809))
- Fix RPC compilation warnings. ([#6808](https://github.com/paritytech/parity/pull/6808))
- Remove internal ipc ([#6795](https://github.com/paritytech/parity/pull/6795))
- Consistent KeyValueDB errors ([#6792](https://github.com/paritytech/parity/pull/6792))
- Squash remaining warnings ([#6789](https://github.com/paritytech/parity/pull/6789))
- Forward-port [#6754](https://github.com/paritytech/parity/issues/6754) [#6755](https://github.com/paritytech/parity/issues/6755) ([#6785](https://github.com/paritytech/parity/pull/6785))
- Removed duplicated versions of clippy ([#6776](https://github.com/paritytech/parity/pull/6776))
- Updated ethabi to version 4.0 ([#6742](https://github.com/paritytech/parity/pull/6742))
- Updated rpc_cli and parity to rpassword 1.0 ([#6774](https://github.com/paritytech/parity/pull/6774))
- Fix sign data typo ([#6750](https://github.com/paritytech/parity/pull/6750))
- Refactoring/cache 6693 ([#6772](https://github.com/paritytech/parity/pull/6772))
- Fix CHANGLOG for 1.8.0 ([#6751](https://github.com/paritytech/parity/pull/6751))
- Removes redundant `mut` in service.rs.in ([#6775](https://github.com/paritytech/parity/pull/6775))
- Remove redundant `mut` ([#6773](https://github.com/paritytech/parity/pull/6773))
- Fixed kovan chain validation ([#6758](https://github.com/paritytech/parity/pull/6758))
- Removed redundant evm deps ([#6757](https://github.com/paritytech/parity/pull/6757))
- Fixed modexp gas calculation overflow ([#6741](https://github.com/paritytech/parity/pull/6741))
- Use cc 1.0 instead of gcc ([#6733](https://github.com/paritytech/parity/pull/6733))
- Version bump to 1.9.0 ([#6727](https://github.com/paritytech/parity/pull/6727))
- Fix badges not showing up ([#6730](https://github.com/paritytech/parity/pull/6730))

View File

@@ -1,6 +1,6 @@
[package]
name = "ethash"
version = "1.11.0"
version = "1.9.0"
authors = ["Parity Technologies <admin@parity.io>"]
[lib]
@@ -14,8 +14,5 @@ crunchy = "0.1.0"
memmap = "0.6"
either = "1.0.0"
[dev-dependencies]
tempdir = "0.3"
[features]
benches = []

View File

@@ -315,7 +315,6 @@ fn calculate_dag_item(node_index: u32, cache: &[Node]) -> Node {
mod test {
use super::*;
use std::fs;
use tempdir::TempDir;
#[test]
fn test_get_cache_size() {
@@ -387,10 +386,8 @@ mod test {
0xe9, 0x7e, 0x53, 0x84,
];
let nonce = 0xd7b3ac70a301a249;
let tempdir = TempDir::new("").unwrap();
// difficulty = 0x085657254bd9u64;
let light = NodeCacheBuilder::new(None).light(tempdir.path(), 486382);
let light = NodeCacheBuilder::new(None).light(&::std::env::temp_dir(), 486382);
let result = light_compute(&light, &hash, nonce);
assert_eq!(result.mix_hash[..], mix_hash[..]);
assert_eq!(result.value[..], boundary[..]);
@@ -398,18 +395,18 @@ mod test {
#[test]
fn test_drop_old_data() {
let tempdir = TempDir::new("").unwrap();
let path = ::std::env::temp_dir();
let builder = NodeCacheBuilder::new(None);
let first = builder.light(tempdir.path(), 0).to_file().unwrap().to_owned();
let first = builder.light(&path, 0).to_file().unwrap().to_owned();
let second = builder.light(tempdir.path(), ETHASH_EPOCH_LENGTH).to_file().unwrap().to_owned();
let second = builder.light(&path, ETHASH_EPOCH_LENGTH).to_file().unwrap().to_owned();
assert!(fs::metadata(&first).is_ok());
let _ = builder.light(tempdir.path(), ETHASH_EPOCH_LENGTH * 2).to_file();
let _ = builder.light(&path, ETHASH_EPOCH_LENGTH * 2).to_file();
assert!(fs::metadata(&first).is_err());
assert!(fs::metadata(&second).is_ok());
let _ = builder.light(tempdir.path(), ETHASH_EPOCH_LENGTH * 3).to_file();
let _ = builder.light(&path, ETHASH_EPOCH_LENGTH * 3).to_file();
assert!(fs::metadata(&second).is_err());
}
}

View File

@@ -26,9 +26,6 @@ extern crate crunchy;
#[macro_use]
extern crate log;
#[cfg(test)]
extern crate tempdir;
mod compute;
mod seed_compute;
mod cache;
@@ -138,10 +135,7 @@ impl EthashManager {
#[test]
fn test_lru() {
use tempdir::TempDir;
let tempdir = TempDir::new("").unwrap();
let ethash = EthashManager::new(tempdir.path(), None);
let ethash = EthashManager::new(&::std::env::temp_dir(), None);
let hash = [0u8; 32];
ethash.compute_light(1, &hash, 1);
ethash.compute_light(50000, &hash, 1);

View File

@@ -3,30 +3,28 @@ description = "Ethcore library"
homepage = "http://parity.io"
license = "GPL-3.0"
name = "ethcore"
version = "1.11.0"
version = "1.9.0"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
ansi_term = "0.10"
bloomchain = { path = "../util/bloomchain" }
bn = { git = "https://github.com/paritytech/bn", default-features = false }
bn = { git = "https://github.com/paritytech/bn" }
byteorder = "1.0"
common-types = { path = "types" }
crossbeam = "0.3"
ethash = { path = "../ethash" }
ethcore-bloom-journal = { path = "../util/bloom" }
ethcore-bytes = { path = "../util/bytes" }
fetch = { path = "../util/fetch" }
hashdb = { path = "../util/hashdb" }
memorydb = { path = "../util/memorydb" }
patricia-trie = { path = "../util/patricia_trie" }
error-chain = { version = "0.11", default-features = false }
ethcore-io = { path = "../util/io" }
ethcore-logger = { path = "../logger" }
ethcore-miner = { path = "../miner" }
ethcore-stratum = { path = "./stratum" }
ethcore-stratum = { path = "../stratum" }
ethcore-transaction = { path = "./transaction" }
ethereum-types = "0.3"
ethereum-types = "0.2"
memory-cache = { path = "../util/memory_cache" }
ethabi = "5.1"
ethabi-derive = "5.0"
@@ -35,57 +33,55 @@ ethjson = { path = "../json" }
ethkey = { path = "../ethkey" }
ethstore = { path = "../ethstore" }
evm = { path = "evm" }
futures-cpupool = "0.1"
hardware-wallet = { path = "../hw" }
heapsize = "0.4"
itertools = "0.5"
lazy_static = "1.0"
log = "0.3"
lru-cache = "0.1"
num = { version = "0.1", default-features = false, features = ["bigint"] }
num = "0.1"
num_cpus = "1.2"
parity-machine = { path = "../machine" }
parking_lot = "0.5"
rayon = "1.0"
price-info = { path = "../price-info" }
rayon = "0.8"
rand = "0.4"
rlp = { path = "../util/rlp" }
rlp_compress = { path = "../util/rlp_compress" }
rlp_derive = { path = "../util/rlp_derive" }
kvdb = { path = "../util/kvdb" }
kvdb-rocksdb = { path = "../util/kvdb-rocksdb" }
kvdb-memorydb = { path = "../util/kvdb-memorydb" }
util-error = { path = "../util/error" }
snappy = { git = "https://github.com/paritytech/rust-snappy" }
stop-guard = { path = "../util/stop-guard" }
migration = { path = "../util/migration" }
macros = { path = "../util/macros" }
rust-crypto = "0.2.34"
rustc-hex = "1.0"
stats = { path = "../util/stats" }
time = "0.1"
trace-time = { path = "../util/trace-time" }
using_queue = { path = "../util/using_queue" }
table = { path = "../util/table" }
vm = { path = "vm" }
wasm = { path = "wasm" }
keccak-hash = { path = "../util/hash" }
triehash = { path = "../util/triehash" }
unexpected = { path = "../util/unexpected" }
journaldb = { path = "../util/journaldb" }
tempdir = "0.3"
[dev-dependencies]
tempdir = "0.3"
trie-standardmap = { path = "../util/trie-standardmap" }
kvdb-rocksdb = { path = "../util/kvdb-rocksdb" }
[features]
# Display EVM debug traces.
jit = ["evm/jit"]
evm-debug = ["slow-blocks"]
# Display EVM debug traces when running tests.
evm-debug-tests = ["evm-debug", "evm/evm-debug-tests"]
# Measure time of transaction execution.
# Whenever the transaction execution time (in millis) exceeds the value of
# SLOW_TX_DURATION env variable (provided compile time!)
# EVM debug traces are printed.
slow-blocks = []
# Run JSON consensus tests.
slow-blocks = [] # Use SLOW_TX_DURATION="50" (compile time!) to track transactions over 50ms
json-tests = ["ethcore-transaction/json-tests"]
# Run memory/cpu heavy tests.
test-heavy = []
# Compile benches
default = []
benches = []

View File

@@ -1,5 +0,0 @@
# Ethcrypto
General cryptographic utilities for Ethereum.
By default, this library is compiled with the `secp256k1` feature, which provides ECDH and ECIES capability on that curve. It can be compiled without to avoid a dependency on the `libsecp256k1` library.

View File

@@ -5,7 +5,8 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
bit-set = "0.4"
ethereum-types = "0.3"
ethereum-types = "0.2"
evmjit = { path = "../../evmjit", optional = true }
heapsize = "0.4"
lazy_static = "1.0"
log = "0.3"
@@ -18,5 +19,6 @@ memory-cache = { path = "../../util/memory_cache" }
rustc-hex = "1.0"
[features]
jit = ["evmjit"]
evm-debug = []
evm-debug-tests = ["evm-debug"]

View File

@@ -32,6 +32,23 @@ pub struct Factory {
impl Factory {
/// Create fresh instance of VM
/// Might choose implementation depending on supplied gas.
#[cfg(feature = "jit")]
pub fn create(&self, gas: &U256) -> Box<Vm> {
match self.evm {
VMType::Jit => {
Box::new(super::jit::JitEvm::default())
},
VMType::Interpreter => if Self::can_fit_in_usize(gas) {
Box::new(super::interpreter::Interpreter::<usize>::new(self.evm_cache.clone()))
} else {
Box::new(super::interpreter::Interpreter::<U256>::new(self.evm_cache.clone()))
}
}
}
/// Create fresh instance of VM
/// Might choose implementation depending on supplied gas.
#[cfg(not(feature = "jit"))]
pub fn create(&self, gas: &U256) -> Box<Vm> {
match self.evm {
VMType::Interpreter => if Self::can_fit_in_usize(gas) {
@@ -57,7 +74,17 @@ impl Factory {
}
impl Default for Factory {
/// Returns jitvm factory
#[cfg(all(feature = "jit", not(test)))]
fn default() -> Factory {
Factory {
evm: VMType::Jit,
evm_cache: Arc::new(SharedCache::default()),
}
}
/// Returns native rust evm factory
#[cfg(any(not(feature = "jit"), test))]
fn default() -> Factory {
Factory {
evm: VMType::Interpreter,
@@ -74,7 +101,24 @@ fn test_create_vm() {
/// Create tests by injecting different VM factories
#[macro_export]
macro_rules! evm_test(
($name_test: ident: $name_int: ident) => {
(ignorejit => $name_test: ident: $name_jit: ident, $name_int: ident) => {
#[test]
#[ignore]
#[cfg(feature = "jit")]
fn $name_jit() {
$name_test(Factory::new(VMType::Jit, 1024 * 32));
}
#[test]
fn $name_int() {
$name_test(Factory::new(VMType::Interpreter, 1024 * 32));
}
};
($name_test: ident: $name_jit: ident, $name_int: ident) => {
#[test]
#[cfg(feature = "jit")]
fn $name_jit() {
$name_test(Factory::new(VMType::Jit, 1024 * 32));
}
#[test]
fn $name_int() {
$name_test(Factory::new(VMType::Interpreter, 1024 * 32));
@@ -85,7 +129,14 @@ macro_rules! evm_test(
/// Create ignored tests by injecting different VM factories
#[macro_export]
macro_rules! evm_test_ignore(
($name_test: ident: $name_int: ident) => {
($name_test: ident: $name_jit: ident, $name_int: ident) => {
#[test]
#[ignore]
#[cfg(feature = "jit")]
#[cfg(feature = "ignored-tests")]
fn $name_jit() {
$name_test(Factory::new(VMType::Jit, 1024 * 32));
}
#[test]
#[ignore]
#[cfg(feature = "ignored-tests")]

View File

@@ -81,7 +81,7 @@ fn test_get_swap_position() {
assert_eq!(get_swap_position(SWAP10), 10);
}
/// Returns number of topics to take from stack
/// Returns number of topcis to take from stack
/// LOG0 -> 0
pub fn get_log_topics (i: Instruction) -> usize {
assert!(i >= LOG0 && i <= LOG4);

414
ethcore/evm/src/jit.rs Normal file
View File

@@ -0,0 +1,414 @@
// Copyright 2015-2017 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/>.
//! Just in time compiler execution environment.
use bigint::prelude::U256;
use bigint::hash::H256;
use util::*;
use evmjit;
use evm::{self, GasLeft};
use evm::CallType;
use vm::{self, Vm};
/// Should be used to convert jit types to ethcore
trait FromJit<T>: Sized {
fn from_jit(input: T) -> Self;
}
/// Should be used to covert ethcore types to jit
trait IntoJit<T> {
fn into_jit(self) -> T;
}
impl<'a> FromJit<&'a evmjit::I256> for U256 {
fn from_jit(input: &'a evmjit::I256) -> Self {
unsafe {
let mut res: U256 = mem::uninitialized();
ptr::copy(input.words.as_ptr(), res.0.as_mut_ptr(), 4);
res
}
}
}
impl<'a> FromJit<&'a evmjit::I256> for H256 {
fn from_jit(input: &'a evmjit::I256) -> Self {
let u = U256::from_jit(input);
H256::from(&u)
}
}
impl<'a> FromJit<&'a evmjit::I256> for Address {
fn from_jit(input: &'a evmjit::I256) -> Self {
Address::from(H256::from_jit(input))
}
}
impl<'a> FromJit<&'a evmjit::H256> for H256 {
fn from_jit(input: &'a evmjit::H256) -> Self {
H256::from_jit(&evmjit::I256::from(input.clone()))
}
}
impl<'a> FromJit<&'a evmjit::H256> for Address {
fn from_jit(input: &'a evmjit::H256) -> Self {
Address::from(H256::from_jit(input))
}
}
impl IntoJit<evmjit::I256> for U256 {
fn into_jit(self) -> evmjit::I256 {
unsafe {
let mut res: evmjit::I256 = mem::uninitialized();
ptr::copy(self.0.as_ptr(), res.words.as_mut_ptr(), 4);
res
}
}
}
impl IntoJit<evmjit::I256> for H256 {
fn into_jit(self) -> evmjit::I256 {
let mut ret = [0; 4];
let len = self.len();
for i in 0..len {
let rev = len - 1 - i;
let pos = rev / 8;
ret[pos] += (self[i] as u64) << ((rev % 8) * 8);
}
evmjit::I256 { words: ret }
}
}
impl IntoJit<evmjit::H256> for H256 {
fn into_jit(self) -> evmjit::H256 {
let i: evmjit::I256 = self.into_jit();
From::from(i)
}
}
impl IntoJit<evmjit::I256> for Address {
fn into_jit(self) -> evmjit::I256 {
H256::from(self).into_jit()
}
}
impl IntoJit<evmjit::H256> for Address {
fn into_jit(self) -> evmjit::H256 {
H256::from(self).into_jit()
}
}
/// Externalities adapter. Maps callbacks from evmjit to externalities trait.
///
/// Evmjit doesn't have to know about children execution failures.
/// This adapter 'catches' them and moves upstream.
struct ExtAdapter<'a> {
ext: &'a mut evm::Ext,
address: Address
}
impl<'a> ExtAdapter<'a> {
fn new(ext: &'a mut evm::Ext, address: Address) -> Self {
ExtAdapter {
ext: ext,
address: address
}
}
}
impl<'a> evmjit::Ext for ExtAdapter<'a> {
fn sload(&self, key: *const evmjit::I256, out_value: *mut evmjit::I256) {
unsafe {
let i = H256::from_jit(&*key);
let o = self.ext.storage_at(&i);
*out_value = o.into_jit();
}
}
fn sstore(&mut self, key: *const evmjit::I256, value: *const evmjit::I256) {
let key = unsafe { H256::from_jit(&*key) };
let value = unsafe { H256::from_jit(&*value) };
let old_value = self.ext.storage_at(&key);
// if SSTORE nonzero -> zero, increment refund count
if !old_value.is_zero() && value.is_zero() {
self.ext.inc_sstore_clears();
}
self.ext.set_storage(key, value);
}
fn balance(&self, address: *const evmjit::H256, out_value: *mut evmjit::I256) {
unsafe {
let a = Address::from_jit(&*address);
let o = self.ext.balance(&a);
*out_value = o.into_jit();
}
}
fn blockhash(&self, number: *const evmjit::I256, out_hash: *mut evmjit::H256) {
unsafe {
let n = U256::from_jit(&*number);
let o = self.ext.blockhash(&n);
*out_hash = o.into_jit();
}
}
fn create(&mut self,
io_gas: *mut u64,
value: *const evmjit::I256,
init_beg: *const u8,
init_size: u64,
address: *mut evmjit::H256) {
let gas = unsafe { U256::from(*io_gas) };
let value = unsafe { U256::from_jit(&*value) };
let code = unsafe { slice::from_raw_parts(init_beg, init_size as usize) };
// check if balance is sufficient and we are not too deep
if self.ext.balance(&self.address) >= value && self.ext.depth() < self.ext.schedule().max_depth {
match self.ext.create(&gas, &value, code) {
evm::ContractCreateResult::Created(new_address, gas_left) => unsafe {
*address = new_address.into_jit();
*io_gas = gas_left.low_u64();
},
evm::ContractCreateResult::Failed => unsafe {
*address = Address::new().into_jit();
*io_gas = 0;
}
}
} else {
unsafe { *address = Address::new().into_jit(); }
}
}
fn call(&mut self,
io_gas: *mut u64,
call_gas: u64,
sender_address: *const evmjit::H256,
receive_address: *const evmjit::H256,
code_address: *const evmjit::H256,
transfer_value: *const evmjit::I256,
// We are ignoring apparent value - it's handled in externalities.
_apparent_value: *const evmjit::I256,
in_beg: *const u8,
in_size: u64,
out_beg: *mut u8,
out_size: u64) -> bool {
let mut gas = unsafe { U256::from(*io_gas) };
let mut call_gas = U256::from(call_gas);
let mut gas_cost = call_gas;
let sender_address = unsafe { Address::from_jit(&*sender_address) };
let receive_address = unsafe { Address::from_jit(&*receive_address) };
let code_address = unsafe { Address::from_jit(&*code_address) };
let transfer_value = unsafe { U256::from_jit(&*transfer_value) };
// receive address and code address are the same in normal calls
let is_callcode = receive_address != code_address;
let is_delegatecall = is_callcode && sender_address != receive_address;
let value = if is_delegatecall { None } else { Some(transfer_value) };
if !is_callcode && !self.ext.exists(&code_address) {
gas_cost = gas_cost + U256::from(self.ext.schedule().call_new_account_gas);
}
if transfer_value > U256::zero() {
assert!(self.ext.schedule().call_value_transfer_gas > self.ext.schedule().call_stipend, "overflow possible");
gas_cost = gas_cost + U256::from(self.ext.schedule().call_value_transfer_gas);
call_gas = call_gas + U256::from(self.ext.schedule().call_stipend);
}
if gas_cost > gas {
unsafe {
*io_gas = -1i64 as u64;
return false;
}
}
gas = gas - gas_cost;
// check if balance is sufficient and we are not too deep
if self.ext.balance(&self.address) < transfer_value || self.ext.depth() >= self.ext.schedule().max_depth {
unsafe {
*io_gas = (gas + call_gas).low_u64();
return false;
}
}
let call_type = match (is_callcode, is_delegatecall) {
(_, true) => CallType::DelegateCall,
(true, false) => CallType::CallCode,
(false, false) => CallType::Call,
};
match self.ext.call(
&call_gas,
&sender_address,
&receive_address,
value,
unsafe { slice::from_raw_parts(in_beg, in_size as usize) },
&code_address,
unsafe { slice::from_raw_parts_mut(out_beg, out_size as usize) },
call_type,
) {
evm::MessageCallResult::Success(gas_left) => unsafe {
*io_gas = (gas + gas_left).low_u64();
true
},
evm::MessageCallResult::Failed => unsafe {
*io_gas = gas.low_u64();
false
}
}
}
fn log(&mut self,
beg: *const u8,
size: u64,
topic1: *const evmjit::H256,
topic2: *const evmjit::H256,
topic3: *const evmjit::H256,
topic4: *const evmjit::H256) {
unsafe {
let mut topics = vec![];
if !topic1.is_null() {
topics.push(H256::from_jit(&*topic1));
}
if !topic2.is_null() {
topics.push(H256::from_jit(&*topic2));
}
if !topic3.is_null() {
topics.push(H256::from_jit(&*topic3));
}
if !topic4.is_null() {
topics.push(H256::from_jit(&*topic4));
}
let bytes_ref: &[u8] = slice::from_raw_parts(beg, size as usize);
self.ext.log(topics, bytes_ref);
}
}
fn extcode(&self, address: *const evmjit::H256, size: *mut u64) -> *const u8 {
unsafe {
let code = self.ext.extcode(&Address::from_jit(&*address));
*size = code.len() as u64;
let ptr = code.as_ptr();
mem::forget(code);
ptr
}
}
}
#[derive(Default)]
pub struct JitEvm {
context: Option<evmjit::ContextHandle>,
}
impl vm::Vm for JitEvm {
fn exec(&mut self, params: ActionParams, ext: &mut evm::Ext) -> evm::Result<GasLeft> {
// Dirty hack. This is unsafe, but we interact with ffi, so it's justified.
let ext_adapter: ExtAdapter<'static> = unsafe { ::std::mem::transmute(ExtAdapter::new(ext, params.address.clone())) };
let mut ext_handle = evmjit::ExtHandle::new(ext_adapter);
assert!(params.gas <= U256::from(i64::max_value() as u64), "evmjit max gas is 2 ^ 63");
assert!(params.gas_price <= U256::from(i64::max_value() as u64), "evmjit max gas is 2 ^ 63");
let call_data = params.data.unwrap_or_else(Vec::new);
let code = params.code.unwrap_or_else(Vec::new);
let mut data = evmjit::RuntimeDataHandle::new();
data.gas = params.gas.low_u64() as i64;
data.gas_price = params.gas_price.low_u64() as i64;
data.call_data = call_data.as_ptr();
data.call_data_size = call_data.len() as u64;
mem::forget(call_data);
data.code = code.as_ptr();
data.code_size = code.len() as u64;
data.code_hash = code.sha3().into_jit();
mem::forget(code);
data.address = params.address.into_jit();
data.caller = params.sender.into_jit();
data.origin = params.origin.into_jit();
data.transfer_value = match params.value {
ActionValue::Transfer(val) => val.into_jit(),
ActionValue::Apparent(val) => val.into_jit()
};
data.apparent_value = data.transfer_value;
let mut schedule = evmjit::ScheduleHandle::new();
schedule.have_delegate_call = ext.schedule().have_delegate_call;
data.author = ext.env_info().author.clone().into_jit();
data.difficulty = ext.env_info().difficulty.into_jit();
data.gas_limit = ext.env_info().gas_limit.into_jit();
data.number = ext.env_info().number;
// don't really know why jit timestamp is int..
data.timestamp = ext.env_info().timestamp as i64;
self.context = Some(unsafe { evmjit::ContextHandle::new(data, schedule, &mut ext_handle) });
let mut context = self.context.as_mut().expect("context handle set on the prior line; qed");
let res = context.exec();
match res {
evmjit::ReturnCode::Stop => Ok(GasLeft::Known(U256::from(context.gas_left()))),
evmjit::ReturnCode::Return =>
Ok(GasLeft::NeedsReturn(U256::from(context.gas_left()), context.output_data())),
evmjit::ReturnCode::Suicide => {
ext.suicide(&Address::from_jit(&context.suicide_refund_address()));
Ok(GasLeft::Known(U256::from(context.gas_left())))
},
evmjit::ReturnCode::OutOfGas => Err(vm::Error::OutOfGas),
_err => Err(vm::Error::Internal)
}
}
}
#[test]
fn test_to_and_from_u256() {
let u = U256::from_str("d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3").unwrap();
let j = u.into_jit();
let u2 = U256::from_jit(&j);
assert_eq!(u, u2);
}
#[test]
fn test_to_and_from_h256() {
let h = H256::from_str("d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3").unwrap();
let j: ::evmjit::I256 = h.clone().into_jit();
let h2 = H256::from_jit(&j);
assert_eq!(h, h2);
let j: ::evmjit::H256 = h.clone().into_jit();
let h2 = H256::from_jit(&j);
assert_eq!(h, h2);
}
#[test]
fn test_to_and_from_address() {
let a = Address::from_str("2adc25665018aa1fe0e6bc666dac8fc2697ff9ba").unwrap();
let j: ::evmjit::I256 = a.clone().into_jit();
let a2 = Address::from_jit(&j);
assert_eq!(a, a2);
let j: ::evmjit::H256 = a.clone().into_jit();
let a2 = Address::from_jit(&j);
assert_eq!(a, a2);
}

View File

@@ -30,6 +30,9 @@ extern crate lazy_static;
#[cfg_attr(feature = "evm-debug", macro_use)]
extern crate log;
#[cfg(feature = "jit")]
extern crate evmjit;
#[cfg(test)]
extern crate rustc_hex;
@@ -41,6 +44,9 @@ pub mod factory;
mod vmtype;
mod instructions;
#[cfg(feature = "jit" )]
mod jit;
#[cfg(test)]
mod tests;
#[cfg(all(feature="benches", test))]

View File

@@ -26,9 +26,9 @@ use vm::tests::{FakeExt, FakeCall, FakeCallType, test_finalize};
use factory::Factory;
use vmtype::VMType;
evm_test!{test_add: test_add_int}
evm_test!{test_add: test_add_jit, test_add_int}
fn test_add(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01600055".from_hex().unwrap();
let mut params = ActionParams::default();
@@ -46,7 +46,7 @@ fn test_add(factory: super::Factory) {
assert_store(&ext, 0, "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe");
}
evm_test!{test_sha3: test_sha3_int}
evm_test!{test_sha3: test_sha3_jit, test_sha3_int}
fn test_sha3(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "6000600020600055".from_hex().unwrap();
@@ -66,7 +66,7 @@ fn test_sha3(factory: super::Factory) {
assert_store(&ext, 0, "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470");
}
evm_test!{test_address: test_address_int}
evm_test!{test_address: test_address_jit, test_address_int}
fn test_address(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "30600055".from_hex().unwrap();
@@ -86,7 +86,7 @@ fn test_address(factory: super::Factory) {
assert_store(&ext, 0, "0000000000000000000000000f572e5295c57f15886f9b263e2f6d2d6c7b5ec6");
}
evm_test!{test_origin: test_origin_int}
evm_test!{test_origin: test_origin_jit, test_origin_int}
fn test_origin(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let origin = Address::from_str("cd1722f2947def4cf144679da39c4c32bdc35681").unwrap();
@@ -108,7 +108,7 @@ fn test_origin(factory: super::Factory) {
assert_store(&ext, 0, "000000000000000000000000cd1722f2947def4cf144679da39c4c32bdc35681");
}
evm_test!{test_sender: test_sender_int}
evm_test!{test_sender: test_sender_jit, test_sender_int}
fn test_sender(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let sender = Address::from_str("cd1722f2947def4cf144679da39c4c32bdc35681").unwrap();
@@ -130,7 +130,7 @@ fn test_sender(factory: super::Factory) {
assert_store(&ext, 0, "000000000000000000000000cd1722f2947def4cf144679da39c4c32bdc35681");
}
evm_test!{test_extcodecopy: test_extcodecopy_int}
evm_test!{test_extcodecopy: test_extcodecopy_jit, test_extcodecopy_int}
fn test_extcodecopy(factory: super::Factory) {
// 33 - sender
// 3b - extcodesize
@@ -165,7 +165,7 @@ fn test_extcodecopy(factory: super::Factory) {
assert_store(&ext, 0, "6005600055000000000000000000000000000000000000000000000000000000");
}
evm_test!{test_log_empty: test_log_empty_int}
evm_test!{test_log_empty: test_log_empty_jit, test_log_empty_int}
fn test_log_empty(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "60006000a0".from_hex().unwrap();
@@ -187,7 +187,7 @@ fn test_log_empty(factory: super::Factory) {
assert!(ext.logs[0].data.is_empty());
}
evm_test!{test_log_sender: test_log_sender_int}
evm_test!{test_log_sender: test_log_sender_jit, test_log_sender_int}
fn test_log_sender(factory: super::Factory) {
// 60 ff - push ff
// 60 00 - push 00
@@ -220,7 +220,7 @@ fn test_log_sender(factory: super::Factory) {
assert_eq!(ext.logs[0].data, "ff00000000000000000000000000000000000000000000000000000000000000".from_hex().unwrap());
}
evm_test!{test_blockhash: test_blockhash_int}
evm_test!{test_blockhash: test_blockhash_jit, test_blockhash_int}
fn test_blockhash(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "600040600055".from_hex().unwrap();
@@ -242,7 +242,7 @@ fn test_blockhash(factory: super::Factory) {
assert_eq!(ext.store.get(&H256::new()).unwrap(), &blockhash);
}
evm_test!{test_calldataload: test_calldataload_int}
evm_test!{test_calldataload: test_calldataload_jit, test_calldataload_int}
fn test_calldataload(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "600135600055".from_hex().unwrap();
@@ -265,7 +265,7 @@ fn test_calldataload(factory: super::Factory) {
}
evm_test!{test_author: test_author_int}
evm_test!{test_author: test_author_jit, test_author_int}
fn test_author(factory: super::Factory) {
let author = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "41600055".from_hex().unwrap();
@@ -285,7 +285,7 @@ fn test_author(factory: super::Factory) {
assert_store(&ext, 0, "0000000000000000000000000f572e5295c57f15886f9b263e2f6d2d6c7b5ec6");
}
evm_test!{test_timestamp: test_timestamp_int}
evm_test!{test_timestamp: test_timestamp_jit, test_timestamp_int}
fn test_timestamp(factory: super::Factory) {
let timestamp = 0x1234;
let code = "42600055".from_hex().unwrap();
@@ -305,7 +305,7 @@ fn test_timestamp(factory: super::Factory) {
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000001234");
}
evm_test!{test_number: test_number_int}
evm_test!{test_number: test_number_jit, test_number_int}
fn test_number(factory: super::Factory) {
let number = 0x1234;
let code = "43600055".from_hex().unwrap();
@@ -325,7 +325,7 @@ fn test_number(factory: super::Factory) {
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000001234");
}
evm_test!{test_difficulty: test_difficulty_int}
evm_test!{test_difficulty: test_difficulty_jit, test_difficulty_int}
fn test_difficulty(factory: super::Factory) {
let difficulty = U256::from(0x1234);
let code = "44600055".from_hex().unwrap();
@@ -345,7 +345,7 @@ fn test_difficulty(factory: super::Factory) {
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000001234");
}
evm_test!{test_gas_limit: test_gas_limit_int}
evm_test!{test_gas_limit: test_gas_limit_jit, test_gas_limit_int}
fn test_gas_limit(factory: super::Factory) {
let gas_limit = U256::from(0x1234);
let code = "45600055".from_hex().unwrap();
@@ -365,7 +365,7 @@ fn test_gas_limit(factory: super::Factory) {
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000001234");
}
evm_test!{test_mul: test_mul_int}
evm_test!{test_mul: test_mul_jit, test_mul_int}
fn test_mul(factory: super::Factory) {
let code = "65012365124623626543219002600055".from_hex().unwrap();
@@ -383,7 +383,7 @@ fn test_mul(factory: super::Factory) {
assert_eq!(gas_left, U256::from(79_983));
}
evm_test!{test_sub: test_sub_int}
evm_test!{test_sub: test_sub_jit, test_sub_int}
fn test_sub(factory: super::Factory) {
let code = "65012365124623626543219003600055".from_hex().unwrap();
@@ -401,7 +401,7 @@ fn test_sub(factory: super::Factory) {
assert_eq!(gas_left, U256::from(79_985));
}
evm_test!{test_div: test_div_int}
evm_test!{test_div: test_div_jit, test_div_int}
fn test_div(factory: super::Factory) {
let code = "65012365124623626543219004600055".from_hex().unwrap();
@@ -419,7 +419,7 @@ fn test_div(factory: super::Factory) {
assert_eq!(gas_left, U256::from(79_983));
}
evm_test!{test_div_zero: test_div_zero_int}
evm_test!{test_div_zero: test_div_zero_jit, test_div_zero_int}
fn test_div_zero(factory: super::Factory) {
let code = "6501236512462360009004600055".from_hex().unwrap();
@@ -437,7 +437,7 @@ fn test_div_zero(factory: super::Factory) {
assert_eq!(gas_left, U256::from(94_983));
}
evm_test!{test_mod: test_mod_int}
evm_test!{test_mod: test_mod_jit, test_mod_int}
fn test_mod(factory: super::Factory) {
let code = "650123651246236265432290066000556501236512462360009006600155".from_hex().unwrap();
@@ -456,7 +456,7 @@ fn test_mod(factory: super::Factory) {
assert_eq!(gas_left, U256::from(74_966));
}
evm_test!{test_smod: test_smod_int}
evm_test!{test_smod: test_smod_jit, test_smod_int}
fn test_smod(factory: super::Factory) {
let code = "650123651246236265432290076000556501236512462360009007600155".from_hex().unwrap();
@@ -475,7 +475,7 @@ fn test_smod(factory: super::Factory) {
assert_eq!(gas_left, U256::from(74_966));
}
evm_test!{test_sdiv: test_sdiv_int}
evm_test!{test_sdiv: test_sdiv_jit, test_sdiv_int}
fn test_sdiv(factory: super::Factory) {
let code = "650123651246236265432290056000556501236512462360009005600155".from_hex().unwrap();
@@ -494,7 +494,7 @@ fn test_sdiv(factory: super::Factory) {
assert_eq!(gas_left, U256::from(74_966));
}
evm_test!{test_exp: test_exp_int}
evm_test!{test_exp: test_exp_jit, test_exp_int}
fn test_exp(factory: super::Factory) {
let code = "6016650123651246230a6000556001650123651246230a6001556000650123651246230a600255".from_hex().unwrap();
@@ -514,7 +514,7 @@ fn test_exp(factory: super::Factory) {
assert_eq!(gas_left, U256::from(39_923));
}
evm_test!{test_comparison: test_comparison_int}
evm_test!{test_comparison: test_comparison_jit, test_comparison_int}
fn test_comparison(factory: super::Factory) {
let code = "601665012365124623818181811060005511600155146002556415235412358014600355".from_hex().unwrap();
@@ -535,7 +535,7 @@ fn test_comparison(factory: super::Factory) {
assert_eq!(gas_left, U256::from(49_952));
}
evm_test!{test_signed_comparison: test_signed_comparison_int}
evm_test!{test_signed_comparison: test_signed_comparison_jit, test_signed_comparison_int}
fn test_signed_comparison(factory: super::Factory) {
let code = "60106000036010818112600055136001556010601060000381811260025513600355".from_hex().unwrap();
@@ -556,7 +556,7 @@ fn test_signed_comparison(factory: super::Factory) {
assert_eq!(gas_left, U256::from(49_940));
}
evm_test!{test_bitops: test_bitops_int}
evm_test!{test_bitops: test_bitops_jit, test_bitops_int}
fn test_bitops(factory: super::Factory) {
let code = "60ff610ff08181818116600055176001551860025560008015600355198015600455600555".from_hex().unwrap();
@@ -579,7 +579,7 @@ fn test_bitops(factory: super::Factory) {
assert_eq!(gas_left, U256::from(44_937));
}
evm_test!{test_addmod_mulmod: test_addmod_mulmod_int}
evm_test!{test_addmod_mulmod: test_addmod_mulmod_jit, test_addmod_mulmod_int}
fn test_addmod_mulmod(factory: super::Factory) {
let code = "60ff60f060108282820860005509600155600060f0601082828208196002550919600355".from_hex().unwrap();
@@ -600,7 +600,7 @@ fn test_addmod_mulmod(factory: super::Factory) {
assert_eq!(gas_left, U256::from(19_914));
}
evm_test!{test_byte: test_byte_int}
evm_test!{test_byte: test_byte_jit, test_byte_int}
fn test_byte(factory: super::Factory) {
let code = "60f061ffff1a600055610fff601f1a600155".from_hex().unwrap();
@@ -619,7 +619,7 @@ fn test_byte(factory: super::Factory) {
assert_eq!(gas_left, U256::from(74_976));
}
evm_test!{test_signextend: test_signextend_int}
evm_test!{test_signextend: test_signextend_jit, test_signextend_int}
fn test_signextend(factory: super::Factory) {
let code = "610fff60020b60005560ff60200b600155".from_hex().unwrap();
@@ -659,7 +659,7 @@ fn test_badinstruction_int() {
}
}
evm_test!{test_pop: test_pop_int}
evm_test!{test_pop: test_pop_jit, test_pop_int}
fn test_pop(factory: super::Factory) {
let code = "60f060aa50600055".from_hex().unwrap();
@@ -677,7 +677,7 @@ fn test_pop(factory: super::Factory) {
assert_eq!(gas_left, U256::from(79_989));
}
evm_test!{test_extops: test_extops_int}
evm_test!{test_extops: test_extops_jit, test_extops_int}
fn test_extops(factory: super::Factory) {
let code = "5a6001555836553a600255386003553460045560016001526016590454600555".from_hex().unwrap();
@@ -702,7 +702,7 @@ fn test_extops(factory: super::Factory) {
assert_eq!(gas_left, U256::from(29_898));
}
evm_test!{test_jumps: test_jumps_int}
evm_test!{test_jumps: test_jumps_jit, test_jumps_int}
fn test_jumps(factory: super::Factory) {
let code = "600160015560066000555b60016000540380806000551560245760015402600155600a565b".from_hex().unwrap();
@@ -722,7 +722,7 @@ fn test_jumps(factory: super::Factory) {
assert_eq!(gas_left, U256::from(54_117));
}
evm_test!{test_calls: test_calls_int}
evm_test!{test_calls: test_calls_jit, test_calls_int}
fn test_calls(factory: super::Factory) {
let code = "600054602d57600160005560006000600060006050610998610100f160006000600060006050610998610100f25b".from_hex().unwrap();
@@ -766,7 +766,7 @@ fn test_calls(factory: super::Factory) {
assert_eq!(ext.calls.len(), 2);
}
evm_test!{test_create_in_staticcall: test_create_in_staticcall_int}
evm_test!{test_create_in_staticcall: test_create_in_staticcall_jit, test_create_in_staticcall_int}
fn test_create_in_staticcall(factory: super::Factory) {
let code = "600060006064f000".from_hex().unwrap();

View File

@@ -19,11 +19,22 @@ use std::fmt;
/// Type of EVM to use.
#[derive(Debug, PartialEq, Clone)]
pub enum VMType {
/// JIT EVM
#[cfg(feature = "jit")]
Jit,
/// RUST EVM
Interpreter
}
impl fmt::Display for VMType {
#[cfg(feature="jit")]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", match *self {
VMType::Jit => "JIT",
VMType::Interpreter => "INT"
})
}
#[cfg(not(feature="jit"))]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", match *self {
VMType::Interpreter => "INT"
@@ -38,8 +49,27 @@ impl Default for VMType {
}
impl VMType {
/// Return all possible VMs (JIT, Interpreter)
#[cfg(feature = "jit")]
pub fn all() -> Vec<VMType> {
vec![VMType::Jit, VMType::Interpreter]
}
/// Return all possible VMs (Interpreter)
#[cfg(not(feature = "jit"))]
pub fn all() -> Vec<VMType> {
vec![VMType::Interpreter]
}
/// Return new jit if it's possible
#[cfg(not(feature = "jit"))]
pub fn jit() -> Option<Self> {
None
}
/// Return new jit if it's possible
#[cfg(feature = "jit")]
pub fn jit() -> Option<Self> {
Some(VMType::Jit)
}
}

View File

@@ -3,7 +3,7 @@ description = "Parity Light Client Implementation"
homepage = "http://parity.io"
license = "GPL-3.0"
name = "ethcore-light"
version = "1.11.0"
version = "1.9.0"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
@@ -11,7 +11,7 @@ log = "0.3"
ethcore = { path = ".."}
ethcore-bytes = { path = "../../util/bytes" }
ethcore-transaction = { path = "../transaction" }
ethereum-types = "0.3"
ethereum-types = "0.2"
memorydb = { path = "../../util/memorydb" }
patricia-trie = { path = "../../util/patricia_trie" }
ethcore-network = { path = "../../util/network" }
@@ -22,6 +22,7 @@ vm = { path = "../vm" }
plain_hasher = { path = "../../util/plain_hasher" }
rlp = { path = "../../util/rlp" }
rlp_derive = { path = "../../util/rlp_derive" }
time = "0.1"
smallvec = "0.4"
futures = "0.1"
rand = "0.4"
@@ -34,11 +35,11 @@ stats = { path = "../../util/stats" }
keccak-hash = { path = "../../util/hash" }
triehash = { path = "../../util/triehash" }
kvdb = { path = "../../util/kvdb" }
kvdb-rocksdb = { path = "../../util/kvdb-rocksdb" }
kvdb-memorydb = { path = "../../util/kvdb-memorydb" }
memory-cache = { path = "../../util/memory_cache" }
error-chain = { version = "0.11", default-features = false }
[dev-dependencies]
kvdb-memorydb = { path = "../../util/kvdb-memorydb" }
tempdir = "0.3"
[features]

View File

@@ -25,7 +25,7 @@ use ethcore::header::BlockNumber;
use ethcore::receipt::Receipt;
use stats::Corpus;
use std::time::{Instant, Duration};
use time::{SteadyTime, Duration};
use heapsize::HeapSizeOf;
use ethereum_types::{H256, U256};
use memory_cache::MemoryLruCache;
@@ -69,7 +69,7 @@ pub struct Cache {
bodies: MemoryLruCache<H256, encoded::Body>,
receipts: MemoryLruCache<H256, Vec<Receipt>>,
chain_score: MemoryLruCache<H256, U256>,
corpus: Option<(Corpus<U256>, Instant)>,
corpus: Option<(Corpus<U256>, SteadyTime)>,
corpus_expiration: Duration,
}
@@ -139,7 +139,7 @@ impl Cache {
/// Get gas price corpus, if recent enough.
pub fn gas_price_corpus(&self) -> Option<Corpus<U256>> {
let now = Instant::now();
let now = SteadyTime::now();
self.corpus.as_ref().and_then(|&(ref corpus, ref tm)| {
if *tm + self.corpus_expiration >= now {
@@ -152,7 +152,7 @@ impl Cache {
/// Set the cached gas price corpus.
pub fn set_gas_price_corpus(&mut self, corpus: Corpus<U256>) {
self.corpus = Some((corpus, Instant::now()))
self.corpus = Some((corpus, SteadyTime::now()))
}
/// Get the memory used.
@@ -175,18 +175,18 @@ impl HeapSizeOf for Cache {
#[cfg(test)]
mod tests {
use super::Cache;
use std::time::Duration;
use time::Duration;
#[test]
fn corpus_inaccessible() {
let mut cache = Cache::new(Default::default(), Duration::from_secs(5 * 3600));
let mut cache = Cache::new(Default::default(), Duration::hours(5));
cache.set_gas_price_corpus(vec![].into());
assert_eq!(cache.gas_price_corpus(), Some(vec![].into()));
{
let corpus_time = &mut cache.corpus.as_mut().unwrap().1;
*corpus_time = *corpus_time - Duration::from_secs(6 * 3600);
*corpus_time = *corpus_time - Duration::hours(6);
}
assert!(cache.gas_price_corpus().is_none());
}

View File

@@ -26,7 +26,7 @@ use hashdb::HashDB;
use memorydb::MemoryDB;
use bytes::Bytes;
use trie::{self, TrieMut, TrieDBMut, Trie, TrieDB, Recorder};
use rlp::{RlpStream, Rlp};
use rlp::{RlpStream, UntrustedRlp};
// encode a key.
macro_rules! key {
@@ -150,7 +150,7 @@ pub fn check_proof(proof: &[Bytes], num: u64, root: H256) -> Option<(H256, U256)
let res = match TrieDB::new(&db, &root) {
Err(_) => return None,
Ok(trie) => trie.get_with(&key!(num), |val: &[u8]| {
let rlp = Rlp::new(val);
let rlp = UntrustedRlp::new(val);
rlp.val_at::<H256>(0)
.and_then(|h| rlp.val_at::<U256>(1).map(|td| (h, td)))
.ok()

View File

@@ -31,21 +31,21 @@ use std::sync::Arc;
use cht;
use ethcore::block_status::BlockStatus;
use ethcore::error::{Error, ErrorKind, BlockImportError, BlockImportErrorKind, BlockError};
use ethcore::error::{BlockImportError, BlockError};
use ethcore::encoded;
use ethcore::header::Header;
use ethcore::ids::BlockId;
use ethcore::spec::{Spec, SpecHardcodedSync};
use ethcore::spec::Spec;
use ethcore::engines::epoch::{
Transition as EpochTransition,
PendingTransition as PendingEpochTransition
};
use rlp::{Encodable, Decodable, DecoderError, RlpStream, Rlp};
use rlp::{Encodable, Decodable, DecoderError, RlpStream, Rlp, UntrustedRlp};
use heapsize::HeapSizeOf;
use ethereum_types::{H256, H264, U256};
use plain_hasher::H256FastMap;
use kvdb::{DBTransaction, KeyValueDB};
use kvdb::{self, DBTransaction, KeyValueDB};
use cache::Cache;
use parking_lot::{Mutex, RwLock};
@@ -74,22 +74,6 @@ pub struct BlockDescriptor {
pub total_difficulty: U256,
}
// best block data
#[derive(RlpEncodable, RlpDecodable)]
struct BestAndLatest {
best_num: u64,
latest_num: u64
}
impl BestAndLatest {
fn new(best_num: u64, latest_num: u64) -> Self {
BestAndLatest {
best_num,
latest_num,
}
}
}
// candidate block description.
struct Candidate {
hash: H256,
@@ -125,7 +109,7 @@ impl Encodable for Entry {
}
impl Decodable for Entry {
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
let mut candidates = SmallVec::<[Candidate; 3]>::new();
for item in rlp.iter() {
@@ -186,7 +170,7 @@ fn encode_canonical_transition(header: &Header, proof: &[u8]) -> Vec<u8> {
// decode last canonical transition entry.
fn decode_canonical_transition(t: &[u8]) -> Result<(Header, &[u8]), DecoderError> {
let rlp = Rlp::new(t);
let rlp = UntrustedRlp::new(t);
Ok((rlp.val_at(0)?, rlp.at(1)?.data()?))
}
@@ -196,12 +180,6 @@ pub struct PendingChanges {
best_block: Option<BlockDescriptor>, // new best block.
}
/// Whether or not the hardcoded sync feature is allowed.
pub enum HardcodedSync {
Allow,
Deny,
}
/// Header chain. See module docs for more details.
pub struct HeaderChain {
genesis_header: encoded::Header, // special-case the genesis.
@@ -220,23 +198,25 @@ impl HeaderChain {
col: Option<u32>,
spec: &Spec,
cache: Arc<Mutex<Cache>>,
allow_hs: HardcodedSync,
) -> Result<Self, Error> {
) -> Result<Self, kvdb::Error> {
let mut live_epoch_proofs = ::std::collections::HashMap::default();
let genesis = ::rlp::encode(&spec.genesis_header()).into_vec();
let decoded_header = spec.genesis_header();
let chain = if let Some(current) = db.get(col, CURRENT_KEY)? {
let curr : BestAndLatest = ::rlp::decode(&current).expect("decoding db value failed");
let (best_number, highest_number) = {
let rlp = Rlp::new(&current);
(rlp.val_at(0), rlp.val_at(1))
};
let mut cur_number = curr.latest_num;
let mut cur_number = highest_number;
let mut candidates = BTreeMap::new();
// load all era entries, referenced headers within them,
// and live epoch proofs.
while let Some(entry) = db.get(col, era_key(cur_number).as_bytes())? {
let entry: Entry = ::rlp::decode(&entry).expect("decoding db value failed");
let entry: Entry = ::rlp::decode(&entry);
trace!(target: "chain", "loaded header chain entry for era {} with {} candidates",
cur_number, entry.candidates.len());
@@ -258,15 +238,15 @@ impl HeaderChain {
// fill best block block descriptor.
let best_block = {
let era = match candidates.get(&curr.best_num) {
let era = match candidates.get(&best_number) {
Some(era) => era,
None => bail!(ErrorKind::Database("Database corrupt: highest block referenced but no data.".into())),
None => return Err("Database corrupt: highest block referenced but no data.".into()),
};
let best = &era.candidates[0];
BlockDescriptor {
hash: best.hash,
number: curr.best_num,
number: best_number,
total_difficulty: best.total_difficulty,
}
};
@@ -280,9 +260,8 @@ impl HeaderChain {
col: col,
cache: cache,
}
} else {
let chain = HeaderChain {
HeaderChain {
genesis_header: encoded::Header::new(genesis),
best_block: RwLock::new(BlockDescriptor {
hash: decoded_header.hash(),
@@ -291,43 +270,10 @@ impl HeaderChain {
}),
candidates: RwLock::new(BTreeMap::new()),
live_epoch_proofs: RwLock::new(live_epoch_proofs),
db: db.clone(),
db: db,
col: col,
cache: cache,
};
// insert the hardcoded sync into the database.
if let (&Some(ref hardcoded_sync), HardcodedSync::Allow) = (&spec.hardcoded_sync, allow_hs) {
let mut batch = db.transaction();
// insert the hardcoded CHT roots into the database.
for (cht_num, cht_root) in hardcoded_sync.chts.iter().enumerate() {
batch.put(col, cht_key(cht_num as u64).as_bytes(), &::rlp::encode(cht_root));
}
let decoded_header = hardcoded_sync.header.decode()?;
let decoded_header_num = decoded_header.number();
// write the block in the DB.
info!(target: "chain", "Inserting hardcoded block #{} in chain",
decoded_header_num);
let pending = chain.insert_with_td(&mut batch, decoded_header,
hardcoded_sync.total_difficulty, None)?;
// check that we have enough hardcoded CHT roots. avoids panicking later.
let cht_num = cht::block_to_cht_number(decoded_header_num - 1)
.expect("specs provided a hardcoded block with height 0");
if cht_num >= hardcoded_sync.chts.len() as u64 {
warn!(target: "chain", "specs didn't provide enough CHT roots for its \
hardcoded block ; falling back to non-hardcoded sync \
mode");
} else {
db.write_buffered(batch);
chain.apply_pending(pending);
}
}
chain
};
// instantiate genesis epoch data if it doesn't exist.
@@ -358,29 +304,6 @@ impl HeaderChain {
transaction: &mut DBTransaction,
header: Header,
transition_proof: Option<Vec<u8>>,
) -> Result<PendingChanges, BlockImportError> {
self.insert_inner(transaction, header, None, transition_proof)
}
/// Insert a pre-verified header, with a known total difficulty. Similary to `insert`.
///
/// This blindly trusts that the data given to it is sensible.
pub fn insert_with_td(
&self,
transaction: &mut DBTransaction,
header: Header,
total_difficulty: U256,
transition_proof: Option<Vec<u8>>,
) -> Result<PendingChanges, BlockImportError> {
self.insert_inner(transaction, header, Some(total_difficulty), transition_proof)
}
fn insert_inner(
&self,
transaction: &mut DBTransaction,
header: Header,
total_difficulty: Option<U256>,
transition_proof: Option<Vec<u8>>,
) -> Result<PendingChanges, BlockImportError> {
let hash = header.hash();
let number = header.number();
@@ -398,24 +321,19 @@ impl HeaderChain {
// hold candidates the whole time to guard import order.
let mut candidates = self.candidates.write();
// find total difficulty.
let total_difficulty = match total_difficulty {
Some(td) => td,
None => {
let parent_td =
if number == 1 {
self.genesis_header.difficulty()
} else {
candidates.get(&(number - 1))
.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)?
};
// find parent details.
let parent_td =
if number == 1 {
self.genesis_header.difficulty()
} else {
candidates.get(&(number - 1))
.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(BlockImportError::Block)?
};
parent_td + *header.difficulty()
},
};
let total_difficulty = parent_td + *header.difficulty();
// insert headers and candidates entries and write era to disk.
{
@@ -524,10 +442,7 @@ impl HeaderChain {
None
}
Ok(None) => panic!("stored candidates always have corresponding headers; qed"),
Ok(Some(header)) => Some((
epoch_transition,
::rlp::decode(&header).expect("decoding value from db failed")
)),
Ok(Some(header)) => Some((epoch_transition, ::rlp::decode(&header))),
};
}
}
@@ -557,71 +472,13 @@ impl HeaderChain {
// write the best and latest eras to the database.
{
let latest_num = *candidates.iter().rev().next().expect("at least one era just inserted; qed").0;
let curr = BestAndLatest::new(best_num, latest_num);
transaction.put(self.col, CURRENT_KEY, &::rlp::encode(&curr))
let mut stream = RlpStream::new_list(2);
stream.append(&best_num).append(&latest_num);
transaction.put(self.col, CURRENT_KEY, &stream.out())
}
Ok(pending)
}
/// Generates the specifications for hardcoded sync. This is typically only called manually
/// from time to time by a Parity developer in order to update the chain specifications.
///
/// Returns `None` if we are at the genesis block, or if an error happens .
pub fn read_hardcoded_sync(&self) -> Result<Option<SpecHardcodedSync>, Error> {
let mut chts = Vec::new();
let mut cht_num = 0;
loop {
let cht = match self.cht_root(cht_num) {
Some(cht) => cht,
None if cht_num != 0 => {
// end of the iteration
let h_num = 1 + cht_num as u64 * cht::SIZE;
let header = if let Some(header) = self.block_header(BlockId::Number(h_num)) {
header
} else {
let msg = format!("header of block #{} not found in DB ; database in an \
inconsistent state", h_num);
bail!(ErrorKind::Database(msg.into()));
};
let decoded = header.decode().expect("decoding db value failed");
let entry: Entry = {
let bytes = self.db.get(self.col, era_key(h_num).as_bytes())?
.ok_or_else(|| {
let msg = format!("entry for era #{} not found in DB ; database \
in an inconsistent state", h_num);
ErrorKind::Database(msg.into())
})?;
::rlp::decode(&bytes).expect("decoding db value failed")
};
let total_difficulty = entry.candidates.iter()
.find(|c| c.hash == decoded.hash())
.ok_or_else(|| {
let msg = "no candidate matching block found in DB ; database in an \
inconsistent state";
ErrorKind::Database(msg.into())
})?
.total_difficulty;
break Ok(Some(SpecHardcodedSync {
header,
total_difficulty,
chts,
}));
},
None => {
break Ok(None);
},
};
chts.push(cht);
cht_num += 1;
}
}
/// Apply pending changes from a previous `insert` operation.
/// Must be done before the next `insert` call.
pub fn apply_pending(&self, pending: PendingChanges) {
@@ -640,7 +497,7 @@ impl HeaderChain {
if self.best_block.read().number < num { return None }
self.candidates.read().get(&num).map(|entry| entry.canonical_hash)
}
BlockId::Latest => {
BlockId::Latest | BlockId::Pending => {
Some(self.best_block.read().hash)
}
}
@@ -682,7 +539,7 @@ impl HeaderChain {
self.candidates.read().get(&num).map(|entry| entry.canonical_hash)
.and_then(load_from_db)
}
BlockId::Latest => {
BlockId::Latest | BlockId::Pending => {
// hold candidates hear to prevent deletion of the header
// as we read it.
let _candidates = self.candidates.read();
@@ -718,7 +575,7 @@ impl HeaderChain {
if self.best_block.read().number < num { return None }
candidates.get(&num).map(|era| era.candidates[0].total_difficulty)
}
BlockId::Latest => Some(self.best_block.read().total_difficulty)
BlockId::Latest | BlockId::Pending => Some(self.best_block.read().total_difficulty)
}
}
@@ -745,7 +602,7 @@ impl HeaderChain {
/// so including it within a CHT would be redundant.
pub fn cht_root(&self, n: usize) -> Option<H256> {
match self.db.get(self.col, cht_key(n as u64).as_bytes()) {
Ok(db_fetch) => db_fetch.map(|bytes| ::rlp::decode(&bytes).expect("decoding value from db failed")),
Ok(val) => val.map(|x| ::rlp::decode(&x)),
Err(e) => {
warn!(target: "chain", "Error reading from database: {}", e);
None
@@ -796,7 +653,7 @@ impl HeaderChain {
pub fn pending_transition(&self, hash: H256) -> Option<PendingEpochTransition> {
let key = pending_transition_key(hash);
match self.db.get(self.col, &*key) {
Ok(db_fetch) => db_fetch.map(|bytes| ::rlp::decode(&bytes).expect("decoding value from db failed")),
Ok(val) => val.map(|x| ::rlp::decode(&x)),
Err(e) => {
warn!(target: "chain", "Error reading from database: {}", e);
None
@@ -815,9 +672,7 @@ impl HeaderChain {
for hdr in self.ancestry_iter(BlockId::Hash(parent_hash)) {
if let Some(transition) = live_proofs.get(&hdr.hash()).cloned() {
return hdr.decode().map(|decoded_hdr| {
(decoded_hdr, transition.proof)
}).ok();
return Some((hdr.decode(), transition.proof))
}
}
@@ -866,7 +721,7 @@ impl<'a> Iterator for AncestryIter<'a> {
#[cfg(test)]
mod tests {
use super::{HeaderChain, HardcodedSync};
use super::HeaderChain;
use std::sync::Arc;
use ethereum_types::U256;
@@ -877,7 +732,7 @@ mod tests {
use kvdb::KeyValueDB;
use kvdb_memorydb;
use std::time::Duration;
use time::Duration;
use parking_lot::Mutex;
fn make_db() -> Arc<KeyValueDB> {
@@ -890,9 +745,9 @@ mod tests {
let genesis_header = spec.genesis_header();
let db = make_db();
let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::from_secs(6 * 3600))));
let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::hours(6))));
let chain = HeaderChain::new(db.clone(), None, &spec, cache, HardcodedSync::Allow).unwrap();
let chain = HeaderChain::new(db.clone(), None, &spec, cache).unwrap();
let mut parent_hash = genesis_header.hash();
let mut rolling_timestamp = genesis_header.timestamp();
@@ -923,9 +778,9 @@ mod tests {
let spec = Spec::new_test();
let genesis_header = spec.genesis_header();
let db = make_db();
let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::from_secs(6 * 3600))));
let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::hours(6))));
let chain = HeaderChain::new(db.clone(), None, &spec, cache, HardcodedSync::Allow).unwrap();
let chain = HeaderChain::new(db.clone(), None, &spec, cache).unwrap();
let mut parent_hash = genesis_header.hash();
let mut rolling_timestamp = genesis_header.timestamp();
@@ -1005,12 +860,13 @@ mod tests {
fn earliest_is_latest() {
let spec = Spec::new_test();
let db = make_db();
let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::from_secs(6 * 3600))));
let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::hours(6))));
let chain = HeaderChain::new(db.clone(), None, &spec, cache, HardcodedSync::Allow).unwrap();
let chain = HeaderChain::new(db.clone(), None, &spec, cache).unwrap();
assert!(chain.block_header(BlockId::Earliest).is_some());
assert!(chain.block_header(BlockId::Latest).is_some());
assert!(chain.block_header(BlockId::Pending).is_some());
}
#[test]
@@ -1018,11 +874,10 @@ mod tests {
let spec = Spec::new_test();
let genesis_header = spec.genesis_header();
let db = make_db();
let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::from_secs(6 * 3600))));
let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::hours(6))));
{
let chain = HeaderChain::new(db.clone(), None, &spec, cache.clone(),
HardcodedSync::Allow).unwrap();
let chain = HeaderChain::new(db.clone(), None, &spec, cache.clone()).unwrap();
let mut parent_hash = genesis_header.hash();
let mut rolling_timestamp = genesis_header.timestamp();
for i in 1..10000 {
@@ -1042,8 +897,7 @@ mod tests {
}
}
let chain = HeaderChain::new(db.clone(), None, &spec, cache.clone(),
HardcodedSync::Allow).unwrap();
let chain = HeaderChain::new(db.clone(), None, &spec, cache.clone()).unwrap();
assert!(chain.block_header(BlockId::Number(10)).is_none());
assert!(chain.block_header(BlockId::Number(9000)).is_some());
assert!(chain.cht_root(2).is_some());
@@ -1056,11 +910,10 @@ mod tests {
let spec = Spec::new_test();
let genesis_header = spec.genesis_header();
let db = make_db();
let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::from_secs(6 * 3600))));
let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::hours(6))));
{
let chain = HeaderChain::new(db.clone(), None, &spec, cache.clone(),
HardcodedSync::Allow).unwrap();
let chain = HeaderChain::new(db.clone(), None, &spec, cache.clone()).unwrap();
let mut parent_hash = genesis_header.hash();
let mut rolling_timestamp = genesis_header.timestamp();
@@ -1102,8 +955,7 @@ mod tests {
}
// after restoration, non-canonical eras should still be loaded.
let chain = HeaderChain::new(db.clone(), None, &spec, cache.clone(),
HardcodedSync::Allow).unwrap();
let chain = HeaderChain::new(db.clone(), None, &spec, cache.clone()).unwrap();
assert_eq!(chain.block_header(BlockId::Latest).unwrap().number(), 10);
assert!(chain.candidates.read().get(&100).is_some())
}
@@ -1113,10 +965,9 @@ mod tests {
let spec = Spec::new_test();
let genesis_header = spec.genesis_header();
let db = make_db();
let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::from_secs(6 * 3600))));
let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::hours(6))));
let chain = HeaderChain::new(db.clone(), None, &spec, cache.clone(),
HardcodedSync::Allow).unwrap();
let chain = HeaderChain::new(db.clone(), None, &spec, cache.clone()).unwrap();
assert!(chain.block_header(BlockId::Earliest).is_some());
assert!(chain.block_header(BlockId::Number(0)).is_some());
@@ -1128,9 +979,9 @@ mod tests {
let spec = Spec::new_test();
let genesis_header = spec.genesis_header();
let db = make_db();
let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::from_secs(6 * 3600))));
let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::hours(6))));
let chain = HeaderChain::new(db.clone(), None, &spec, cache, HardcodedSync::Allow).unwrap();
let chain = HeaderChain::new(db.clone(), None, &spec, cache).unwrap();
let mut parent_hash = genesis_header.hash();
let mut rolling_timestamp = genesis_header.timestamp();
@@ -1188,45 +1039,4 @@ mod tests {
assert!(chain.live_epoch_proofs.read().is_empty());
assert_eq!(chain.epoch_transition_for(parent_hash).unwrap().1, vec![1, 2, 3, 4]);
}
#[test]
fn hardcoded_sync_gen() {
let spec = Spec::new_test();
let genesis_header = spec.genesis_header();
let db = make_db();
let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::from_secs(6 * 3600))));
let chain = HeaderChain::new(db.clone(), None, &spec, cache, HardcodedSync::Allow).expect("failed to instantiate a new HeaderChain");
let mut parent_hash = genesis_header.hash();
let mut rolling_timestamp = genesis_header.timestamp();
let mut total_difficulty = *genesis_header.difficulty();
let h_num = 3 * ::cht::SIZE + 1;
for i in 1..10000 {
let mut header = Header::new();
header.set_parent_hash(parent_hash);
header.set_number(i);
header.set_timestamp(rolling_timestamp);
let diff = *genesis_header.difficulty() * i as u32;
header.set_difficulty(diff);
if i <= h_num {
total_difficulty = total_difficulty + diff;
}
parent_hash = header.hash();
let mut tx = db.transaction();
let pending = chain.insert(&mut tx, header, None).expect("failed inserting a transaction");
db.write(tx).unwrap();
chain.apply_pending(pending);
rolling_timestamp += 10;
}
let hardcoded_sync = chain.read_hardcoded_sync().expect("failed reading hardcoded sync").expect("failed unwrapping hardcoded sync");
assert_eq!(hardcoded_sync.chts.len(), 3);
assert_eq!(hardcoded_sync.total_difficulty, total_difficulty);
let decoded: Header = hardcoded_sync.header.decode().expect("decoding failed");
assert_eq!(decoded.number(), h_num);
}
}

View File

@@ -19,25 +19,27 @@
use std::sync::{Weak, Arc};
use ethcore::block_status::BlockStatus;
use ethcore::client::{ClientReport, EnvInfo, ClientIoMessage};
use ethcore::client::{ClientReport, EnvInfo};
use ethcore::engines::{epoch, EthEngine, EpochChange, EpochTransition, Proof};
use ethcore::machine::EthereumMachine;
use ethcore::error::{Error, BlockImportError};
use ethcore::error::BlockImportError;
use ethcore::ids::BlockId;
use ethcore::header::{BlockNumber, Header};
use ethcore::verification::queue::{self, HeaderQueue};
use ethcore::blockchain_info::BlockChainInfo;
use ethcore::spec::{Spec, SpecHardcodedSync};
use ethcore::spec::Spec;
use ethcore::service::ClientIoMessage;
use ethcore::encoded;
use io::IoChannel;
use parking_lot::{Mutex, RwLock};
use ethereum_types::{H256, U256};
use futures::{IntoFuture, Future};
use kvdb::KeyValueDB;
use kvdb::{self, KeyValueDB};
use kvdb_rocksdb::CompactionProfile;
use self::fetch::ChainDataFetcher;
use self::header_chain::{AncestryIter, HeaderChain, HardcodedSync};
use self::header_chain::{AncestryIter, HeaderChain};
use cache::Cache;
@@ -55,12 +57,16 @@ pub struct Config {
pub queue: queue::Config,
/// Chain column in database.
pub chain_column: Option<u32>,
/// Database cache size. `None` => rocksdb default.
pub db_cache_size: Option<usize>,
/// State db compaction profile
pub db_compaction: CompactionProfile,
/// Should db have WAL enabled?
pub db_wal: bool,
/// Should it do full verification of blocks?
pub verify_full: bool,
/// Should it check the seal of blocks?
pub check_seal: bool,
/// Disable hardcoded sync.
pub no_hardcoded_sync: bool,
}
impl Default for Config {
@@ -68,9 +74,11 @@ impl Default for Config {
Config {
queue: Default::default(),
chain_column: None,
db_cache_size: None,
db_compaction: CompactionProfile::default(),
db_wal: true,
verify_full: true,
check_seal: true,
no_hardcoded_sync: false,
}
}
}
@@ -178,14 +186,11 @@ impl<T: ChainDataFetcher> Client<T> {
fetcher: T,
io_channel: IoChannel<ClientIoMessage>,
cache: Arc<Mutex<Cache>>
) -> Result<Self, Error> {
) -> Result<Self, kvdb::Error> {
Ok(Client {
queue: HeaderQueue::new(config.queue, spec.engine.clone(), io_channel, config.check_seal),
engine: spec.engine.clone(),
chain: {
let hs_cfg = if config.no_hardcoded_sync { HardcodedSync::Deny } else { HardcodedSync::Allow };
HeaderChain::new(db.clone(), chain_col, &spec, cache, hs_cfg)?
},
chain: HeaderChain::new(db.clone(), chain_col, &spec, cache)?,
report: RwLock::new(ClientReport::default()),
import_lock: Mutex::new(()),
db: db,
@@ -195,19 +200,33 @@ impl<T: ChainDataFetcher> Client<T> {
})
}
/// Generates the specifications for hardcoded sync. This is typically only called manually
/// from time to time by a Parity developer in order to update the chain specifications.
///
/// Returns `None` if we are at the genesis block.
pub fn read_hardcoded_sync(&self) -> Result<Option<SpecHardcodedSync>, Error> {
self.chain.read_hardcoded_sync()
}
/// Adds a new `LightChainNotify` listener.
pub fn add_listener(&self, listener: Weak<LightChainNotify>) {
self.listeners.write().push(listener);
}
/// Create a new `Client` backed purely in-memory.
/// This will ignore all database options in the configuration.
pub fn in_memory(
config: Config,
spec: &Spec,
fetcher: T,
io_channel: IoChannel<ClientIoMessage>,
cache: Arc<Mutex<Cache>>
) -> Self {
let db = ::kvdb_memorydb::create(0);
Client::new(
config,
Arc::new(db),
None,
spec,
fetcher,
io_channel,
cache
).expect("New DB creation infallible; qed")
}
/// 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)
@@ -318,7 +337,7 @@ impl<T: ChainDataFetcher> Client<T> {
let epoch_proof = self.engine.is_epoch_end(
&verified_header,
&|h| self.chain.block_header(BlockId::Hash(h)).and_then(|hdr| hdr.decode().ok()),
&|h| self.chain.block_header(BlockId::Hash(h)).map(|hdr| hdr.decode()),
&|h| self.chain.pending_transition(h),
);
@@ -426,15 +445,7 @@ impl<T: ChainDataFetcher> Client<T> {
};
// Verify Block Family
let verify_family_result = {
parent_header.decode()
.map_err(|dec_err| dec_err.into())
.and_then(|decoded| {
self.engine.verify_block_family(&verified_header, &decoded)
})
};
let verify_family_result = self.engine.verify_block_family(&verified_header, &parent_header.decode());
if let Err(e) = verify_family_result {
warn!(target: "client", "Stage 3 block verification failed for #{} ({})\nError: {:?}",
verified_header.number(), verified_header.hash(), e);
@@ -595,12 +606,6 @@ impl<T: ChainDataFetcher> LightChainClient for Client<T> {
}
}
impl<T: ChainDataFetcher> ::ethcore::client::ChainInfo for Client<T> {
fn chain_info(&self) -> BlockChainInfo {
Client::chain_info(self)
}
}
impl<T: ChainDataFetcher> ::ethcore::client::EngineClient for Client<T> {
fn update_sealing(&self) { }
fn submit_seal(&self, _block_hash: H256, _seal: Vec<Vec<u8>>) { }
@@ -614,6 +619,10 @@ impl<T: ChainDataFetcher> ::ethcore::client::EngineClient for Client<T> {
})
}
fn chain_info(&self) -> BlockChainInfo {
Client::chain_info(self)
}
fn as_full_client(&self) -> Option<&::ethcore::client::BlockChainClient> {
None
}

View File

@@ -18,40 +18,34 @@
//! Just handles block import messages and passes them to the client.
use std::fmt;
use std::path::Path;
use std::sync::Arc;
use ethcore::client::ClientIoMessage;
use ethcore::db;
use ethcore::error::Error as CoreError;
use ethcore::service::ClientIoMessage;
use ethcore::spec::Spec;
use io::{IoContext, IoError, IoHandler, IoService};
use kvdb::KeyValueDB;
use kvdb;
use kvdb_rocksdb::{Database, DatabaseConfig};
use cache::Cache;
use parking_lot::Mutex;
use super::{ChainDataFetcher, LightChainNotify, Client, Config as ClientConfig};
use super::{ChainDataFetcher, Client, Config as ClientConfig};
/// Errors on service initialization.
#[derive(Debug)]
pub enum Error {
/// Core error.
Core(CoreError),
/// Database error.
Database(kvdb::Error),
/// I/O service error.
Io(IoError),
}
impl From<CoreError> for Error {
#[inline]
fn from(err: CoreError) -> Error {
Error::Core(err)
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::Core(ref msg) => write!(f, "Core error: {}", msg),
Error::Database(ref msg) => write!(f, "Database error: {}", msg),
Error::Io(ref err) => write!(f, "I/O service error: {}", err),
}
}
@@ -65,7 +59,19 @@ pub struct Service<T> {
impl<T: ChainDataFetcher> Service<T> {
/// Start the service: initialize I/O workers and client itself.
pub fn start(config: ClientConfig, spec: &Spec, fetcher: T, db: Arc<KeyValueDB>, cache: Arc<Mutex<Cache>>) -> Result<Self, Error> {
pub fn start(config: ClientConfig, spec: &Spec, fetcher: T, path: &Path, cache: Arc<Mutex<Cache>>) -> Result<Self, Error> {
// initialize database.
let mut db_config = DatabaseConfig::with_columns(db::NUM_COLUMNS);
db_config.memory_budget = config.db_cache_size;
db_config.compaction = config.db_compaction;
db_config.wal = config.db_wal;
let db = Arc::new(Database::open(
&db_config,
&path.to_str().expect("DB path could not be converted to string.")
).map_err(Error::Database)?);
let io_service = IoService::<ClientIoMessage>::start().map_err(Error::Io)?;
let client = Arc::new(Client::new(config,
@@ -75,7 +81,7 @@ impl<T: ChainDataFetcher> Service<T> {
fetcher,
io_service.channel(),
cache,
)?);
).map_err(Error::Database)?);
io_service.register_handler(Arc::new(ImportBlocks(client.clone()))).map_err(Error::Io)?;
spec.engine.register_client(Arc::downgrade(&client) as _);
@@ -86,11 +92,6 @@ impl<T: ChainDataFetcher> Service<T> {
})
}
/// Set the actor to be notified on certain chain events
pub fn add_notify(&self, notify: Arc<LightChainNotify>) {
self.client.add_listener(Arc::downgrade(&notify));
}
/// Register an I/O handler on the service.
pub fn register_handler(&self, handler: Arc<IoHandler<ClientIoMessage> + Send>) -> Result<(), IoError> {
self.io_service.register_handler(handler)
@@ -120,17 +121,16 @@ mod tests {
use std::sync::Arc;
use cache::Cache;
use client::fetch;
use std::time::Duration;
use time::Duration;
use parking_lot::Mutex;
use kvdb_memorydb;
use ethcore::db::NUM_COLUMNS;
use tempdir::TempDir;
#[test]
fn it_works() {
let db = Arc::new(kvdb_memorydb::create(NUM_COLUMNS.unwrap_or(0)));
let tempdir = TempDir::new("").unwrap();
let spec = Spec::new_test();
let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::from_secs(6 * 3600))));
let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::hours(6))));
Service::start(Default::default(), &spec, fetch::unavailable(), db, cache).unwrap();
Service::start(Default::default(), &spec, fetch::unavailable(), tempdir.path(), cache).unwrap();
}
}

View File

@@ -75,15 +75,14 @@ extern crate rlp_derive;
extern crate serde;
extern crate smallvec;
extern crate stats;
extern crate time;
extern crate vm;
extern crate keccak_hash as hash;
extern crate triehash;
extern crate kvdb;
extern crate kvdb_memorydb;
extern crate kvdb_rocksdb;
extern crate memory_cache;
#[macro_use]
extern crate error_chain;
#[cfg(test)]
extern crate kvdb_memorydb;
#[cfg(test)]
extern crate tempdir;

View File

@@ -47,7 +47,7 @@ pub trait IoContext {
}
impl<T> IoContext for T where T: ?Sized + NetworkContext {
impl<'a> IoContext for NetworkContext<'a> {
fn send(&self, peer: PeerId, packet_id: u8, packet_body: Vec<u8>) {
if let Err(e) = self.send(peer, packet_id, packet_body) {
debug!(target: "pip", "Error sending packet to peer {}: {}", peer, e);

View File

@@ -27,11 +27,11 @@
use std::collections::{HashMap, VecDeque};
use std::fs::File;
use std::path::PathBuf;
use std::time::{Duration, Instant};
use request::{CompleteRequest, Kind};
use bincode;
use time;
use parking_lot::{RwLock, Mutex};
/// Number of time periods samples should be kept for.
@@ -48,11 +48,11 @@ pub trait SampleStore: Send + Sync {
}
// get a hardcoded, arbitrarily determined (but intended overestimate)
// of the time it takes to serve a request of the given kind.
// of the time in nanoseconds to serve a request of the given kind.
//
// TODO: seed this with empirical data.
fn hardcoded_serve_time(kind: Kind) -> Duration {
Duration::new(0, match kind {
fn hardcoded_serve_time(kind: Kind) -> u64 {
match kind {
Kind::Headers => 500_000,
Kind::HeaderProof => 500_000,
Kind::TransactionIndex => 500_000,
@@ -63,7 +63,7 @@ fn hardcoded_serve_time(kind: Kind) -> Duration {
Kind::Code => 1_500_000,
Kind::Execution => 250, // per gas.
Kind::Signal => 500_000,
})
}
}
/// A no-op store.
@@ -107,17 +107,17 @@ impl LoadDistribution {
};
LoadTimer {
start: Instant::now(),
start: time::precise_time_ns(),
n: n,
dist: self,
kind: kind,
}
}
/// Calculate EMA of load for a specific request kind.
/// Calculate EMA of load in nanoseconds for a specific request kind.
/// If there is no data for the given request kind, no EMA will be calculated,
/// but a hardcoded time will be returned.
pub fn expected_time(&self, kind: Kind) -> Duration {
pub fn expected_time_ns(&self, kind: Kind) -> u64 {
let samples = self.samples.read();
samples.get(&kind).and_then(|s| {
if s.len() == 0 { return None }
@@ -128,9 +128,7 @@ impl LoadDistribution {
(alpha * c as f64) + ((1.0 - alpha) * a)
});
// TODO: use `Duration::from_nanos` once stable (https://github.com/rust-lang/rust/issues/46507)
let ema = ema as u64;
Some(Duration::new(ema / 1_000_000_000, (ema % 1_000_000_000) as u32))
Some(ema as u64)
}).unwrap_or_else(move || hardcoded_serve_time(kind))
}
@@ -153,10 +151,10 @@ impl LoadDistribution {
store.store(&*samples);
}
fn update(&self, kind: Kind, elapsed: Duration, n: u64) {
fn update(&self, kind: Kind, elapsed: u64, n: u64) {
macro_rules! update_counters {
($counters: expr) => {
$counters.0 = $counters.0.saturating_add({ elapsed.as_secs() * 1_000_000_000 + elapsed.subsec_nanos() as u64 });
$counters.0 = $counters.0.saturating_add(elapsed);
$counters.1 = $counters.1.saturating_add(n);
}
};
@@ -182,7 +180,7 @@ impl LoadDistribution {
/// A timer for a single request.
/// On drop, this will update the distribution.
pub struct LoadTimer<'a> {
start: Instant,
start: u64,
n: u64,
dist: &'a LoadDistribution,
kind: Kind,
@@ -190,7 +188,7 @@ pub struct LoadTimer<'a> {
impl<'a> Drop for LoadTimer<'a> {
fn drop(&mut self) {
let elapsed = self.start.elapsed();
let elapsed = time::precise_time_ns() - self.start;
self.dist.update(self.kind, elapsed, self.n);
}
}
@@ -225,12 +223,12 @@ mod tests {
#[test]
fn hardcoded_before_data() {
let dist = LoadDistribution::load(&NullStore);
assert_eq!(dist.expected_time(Kind::Headers), hardcoded_serve_time(Kind::Headers));
assert_eq!(dist.expected_time_ns(Kind::Headers), hardcoded_serve_time(Kind::Headers));
dist.update(Kind::Headers, Duration::new(0, 100_000), 100);
dist.update(Kind::Headers, 100_000, 100);
dist.end_period(&NullStore);
assert_eq!(dist.expected_time(Kind::Headers), Duration::new(0, 1000));
assert_eq!(dist.expected_time_ns(Kind::Headers), 1000);
}
#[test]
@@ -240,26 +238,26 @@ mod tests {
let mut sum = 0;
for (i, x) in (0..10).map(|x| x * 10_000).enumerate() {
dist.update(Kind::Headers, Duration::new(0, x), 1);
dist.update(Kind::Headers, x, 1);
dist.end_period(&NullStore);
sum += x;
if i == 0 { continue }
let moving_average = dist.expected_time(Kind::Headers);
let moving_average = dist.expected_time_ns(Kind::Headers);
// should be weighted below the maximum entry.
let arith_average = (sum as f64 / (i + 1) as f64) as u32;
assert!(moving_average < Duration::new(0, x));
let arith_average = (sum as f64 / (i + 1) as f64) as u64;
assert!(moving_average < x);
// when there are only 2 entries, they should be equal due to choice of
// ALPHA = 1/N.
// otherwise, the weight should be below the arithmetic mean because the much
// smaller previous values are discounted less.
if i == 1 {
assert_eq!(moving_average, Duration::new(0, arith_average));
assert_eq!(moving_average, arith_average);
} else {
assert!(moving_average < Duration::new(0, arith_average))
assert!(moving_average < arith_average)
}
}
}

View File

@@ -22,11 +22,11 @@ use transaction::UnverifiedTransaction;
use io::TimerToken;
use network::{HostInfo, NetworkProtocolHandler, NetworkContext, PeerId};
use rlp::{RlpStream, Rlp};
use rlp::{RlpStream, UntrustedRlp};
use ethereum_types::{H256, U256};
use kvdb::DBValue;
use parking_lot::{Mutex, RwLock};
use std::time::{Duration, Instant};
use time::{Duration, SteadyTime};
use std::collections::{HashMap, HashSet};
use std::fmt;
@@ -61,31 +61,28 @@ pub use self::load_timer::{SampleStore, FileStore};
pub use self::status::{Status, Capabilities, Announcement};
const TIMEOUT: TimerToken = 0;
const TIMEOUT_INTERVAL: Duration = Duration::from_secs(1);
const TIMEOUT_INTERVAL_MS: u64 = 1000;
const TICK_TIMEOUT: TimerToken = 1;
const TICK_TIMEOUT_INTERVAL: Duration = Duration::from_secs(5);
const TICK_TIMEOUT_INTERVAL_MS: u64 = 5000;
const PROPAGATE_TIMEOUT: TimerToken = 2;
const PROPAGATE_TIMEOUT_INTERVAL: Duration = Duration::from_secs(5);
const PROPAGATE_TIMEOUT_INTERVAL_MS: u64 = 5000;
const RECALCULATE_COSTS_TIMEOUT: TimerToken = 3;
const RECALCULATE_COSTS_INTERVAL: Duration = Duration::from_secs(60 * 60);
const RECALCULATE_COSTS_INTERVAL_MS: u64 = 60 * 60 * 1000;
// minimum interval between updates.
const UPDATE_INTERVAL: Duration = Duration::from_millis(5000);
/// Packet count for PIP.
const PACKET_COUNT_V1: u8 = 9;
const UPDATE_INTERVAL_MS: i64 = 5000;
/// Supported protocol versions.
pub const PROTOCOL_VERSIONS: &'static [(u8, u8)] = &[
(1, PACKET_COUNT_V1),
];
pub const PROTOCOL_VERSIONS: &'static [u8] = &[1];
/// Max protocol version.
pub const MAX_PROTOCOL_VERSION: u8 = 1;
/// Packet count for PIP.
pub const PACKET_COUNT: u8 = 9;
// packet ID definitions.
mod packet {
@@ -112,22 +109,20 @@ mod packet {
// timeouts for different kinds of requests. all values are in milliseconds.
mod timeout {
use std::time::Duration;
pub const HANDSHAKE: Duration = Duration::from_millis(4_000);
pub const ACKNOWLEDGE_UPDATE: Duration = Duration::from_millis(5_000);
pub const BASE: u64 = 2_500; // base timeout for packet.
pub const HANDSHAKE: i64 = 2500;
pub const ACKNOWLEDGE_UPDATE: i64 = 5000;
pub const BASE: i64 = 1500; // base timeout for packet.
// timeouts per request within packet.
pub const HEADERS: u64 = 250; // per header?
pub const TRANSACTION_INDEX: u64 = 100;
pub const BODY: u64 = 50;
pub const RECEIPT: u64 = 50;
pub const PROOF: u64 = 100; // state proof
pub const CONTRACT_CODE: u64 = 100;
pub const HEADER_PROOF: u64 = 100;
pub const TRANSACTION_PROOF: u64 = 1000; // per gas?
pub const EPOCH_SIGNAL: u64 = 200;
pub const HEADERS: i64 = 250; // per header?
pub const TRANSACTION_INDEX: i64 = 100;
pub const BODY: i64 = 50;
pub const RECEIPT: i64 = 50;
pub const PROOF: i64 = 100; // state proof
pub const CONTRACT_CODE: i64 = 100;
pub const HEADER_PROOF: i64 = 100;
pub const TRANSACTION_PROOF: i64 = 1000; // per gas?
pub const EPOCH_SIGNAL: i64 = 200;
}
/// A request id.
@@ -149,7 +144,7 @@ impl fmt::Display for ReqId {
// may not have received one for.
struct PendingPeer {
sent_head: H256,
last_update: Instant,
last_update: SteadyTime,
}
/// Relevant data to each peer. Not accessible publicly, only `pub` due to
@@ -160,13 +155,13 @@ pub struct Peer {
capabilities: Capabilities,
remote_flow: Option<(Credits, FlowParams)>,
sent_head: H256, // last chain head we've given them.
last_update: Instant,
last_update: SteadyTime,
pending_requests: RequestSet,
failed_requests: Vec<ReqId>,
propagated_transactions: HashSet<H256>,
skip_update: bool,
local_flow: Arc<FlowParams>,
awaiting_acknowledge: Option<(Instant, Arc<FlowParams>)>,
awaiting_acknowledge: Option<(SteadyTime, Arc<FlowParams>)>,
}
/// Whether or not a peer was kept by a handler
@@ -372,9 +367,9 @@ impl LightProtocol {
let sample_store = params.sample_store.unwrap_or_else(|| Box::new(NullStore));
let load_distribution = LoadDistribution::load(&*sample_store);
let flow_params = FlowParams::from_request_times(
|kind| load_distribution.expected_time(kind),
|kind| load_distribution.expected_time_ns(kind),
params.config.load_share,
Duration::from_secs(params.config.max_stored_seconds),
params.config.max_stored_seconds,
);
LightProtocol {
@@ -452,7 +447,7 @@ impl LightProtocol {
});
// begin timeout.
peer.pending_requests.insert(req_id, requests, cost, Instant::now());
peer.pending_requests.insert(req_id, requests, cost, SteadyTime::now());
Ok(req_id)
}
}
@@ -462,7 +457,7 @@ impl LightProtocol {
/// The announcement is expected to be valid.
pub fn make_announcement(&self, io: &IoContext, mut announcement: Announcement) {
let mut reorgs_map = HashMap::new();
let now = Instant::now();
let now = SteadyTime::now();
// update stored capabilities
self.capabilities.write().update_from(&announcement);
@@ -475,7 +470,7 @@ impl LightProtocol {
// the timer approach will skip 1 (possibly 2) in rare occasions.
if peer_info.sent_head == announcement.head_hash ||
peer_info.status.head_num >= announcement.head_num ||
now - peer_info.last_update < UPDATE_INTERVAL {
now - peer_info.last_update < Duration::milliseconds(UPDATE_INTERVAL_MS) {
continue
}
@@ -531,7 +526,7 @@ impl LightProtocol {
// - check whether peer exists
// - check whether request was made
// - check whether request kinds match
fn pre_verify_response(&self, peer: &PeerId, raw: &Rlp) -> Result<IdGuard, Error> {
fn pre_verify_response(&self, peer: &PeerId, raw: &UntrustedRlp) -> Result<IdGuard, Error> {
let req_id = ReqId(raw.val_at(0)?);
let cur_credits: U256 = raw.val_at(1)?;
@@ -542,7 +537,7 @@ impl LightProtocol {
Some(peer_info) => {
let mut peer_info = peer_info.lock();
let peer_info: &mut Peer = &mut *peer_info;
let req_info = peer_info.pending_requests.remove(&req_id, Instant::now());
let req_info = peer_info.pending_requests.remove(&req_id, SteadyTime::now());
let last_batched = peer_info.pending_requests.is_empty();
let flow_info = peer_info.remote_flow.as_mut();
@@ -575,7 +570,7 @@ impl LightProtocol {
/// Packet data is _untrusted_, which means that invalid data won't lead to
/// issues.
pub fn handle_packet(&self, io: &IoContext, peer: &PeerId, packet_id: u8, data: &[u8]) {
let rlp = Rlp::new(data);
let rlp = UntrustedRlp::new(data);
trace!(target: "pip", "Incoming packet {} from peer {}", packet_id, peer);
@@ -604,14 +599,14 @@ impl LightProtocol {
// check timeouts and punish peers.
fn timeout_check(&self, io: &IoContext) {
let now = Instant::now();
let now = SteadyTime::now();
// handshake timeout
{
let mut pending = self.pending_peers.write();
let slowpokes: Vec<_> = pending.iter()
.filter(|&(_, ref peer)| {
peer.last_update + timeout::HANDSHAKE <= now
peer.last_update + Duration::milliseconds(timeout::HANDSHAKE) <= now
})
.map(|(&p, _)| p)
.collect();
@@ -624,7 +619,7 @@ impl LightProtocol {
}
// request and update ack timeouts
let ack_duration = timeout::ACKNOWLEDGE_UPDATE;
let ack_duration = Duration::milliseconds(timeout::ACKNOWLEDGE_UPDATE);
{
for (peer_id, peer) in self.peers.read().iter() {
let peer = peer.lock();
@@ -691,7 +686,7 @@ impl LightProtocol {
Err(e) => { punish(*peer, io, e); return }
};
if PROTOCOL_VERSIONS.iter().find(|x| x.0 == proto_version).is_none() {
if PROTOCOL_VERSIONS.iter().find(|x| **x == proto_version).is_none() {
punish(*peer, io, Error::UnsupportedProtocolVersion(proto_version));
return;
}
@@ -714,7 +709,7 @@ impl LightProtocol {
self.pending_peers.write().insert(*peer, PendingPeer {
sent_head: chain_info.best_block_hash,
last_update: Instant::now(),
last_update: SteadyTime::now(),
});
trace!(target: "pip", "Sending status to peer {}", peer);
@@ -769,14 +764,14 @@ impl LightProtocol {
self.load_distribution.end_period(&*self.sample_store);
let new_params = Arc::new(FlowParams::from_request_times(
|kind| self.load_distribution.expected_time(kind),
|kind| self.load_distribution.expected_time_ns(kind),
self.config.load_share,
Duration::from_secs(self.config.max_stored_seconds),
self.config.max_stored_seconds,
));
*self.flow_params.write() = new_params.clone();
let peers = self.peers.read();
let now = Instant::now();
let now = SteadyTime::now();
let packet_body = {
let mut stream = RlpStream::new_list(3);
@@ -797,7 +792,7 @@ impl LightProtocol {
impl LightProtocol {
// Handle status message from peer.
fn status(&self, peer: &PeerId, io: &IoContext, data: Rlp) -> Result<(), Error> {
fn status(&self, peer: &PeerId, io: &IoContext, data: UntrustedRlp) -> Result<(), Error> {
let pending = match self.pending_peers.write().remove(peer) {
Some(pending) => pending,
None => {
@@ -858,7 +853,7 @@ impl LightProtocol {
}
// Handle an announcement.
fn announcement(&self, peer: &PeerId, io: &IoContext, data: Rlp) -> Result<(), Error> {
fn announcement(&self, peer: &PeerId, io: &IoContext, data: UntrustedRlp) -> Result<(), Error> {
if !self.peers.read().contains_key(peer) {
debug!(target: "pip", "Ignoring announcement from unknown peer");
return Ok(())
@@ -903,7 +898,7 @@ impl LightProtocol {
}
// Receive requests from a peer.
fn request(&self, peer_id: &PeerId, io: &IoContext, raw: Rlp) -> Result<(), Error> {
fn request(&self, peer_id: &PeerId, io: &IoContext, raw: UntrustedRlp) -> Result<(), Error> {
// the maximum amount of requests we'll fill in a single packet.
const MAX_REQUESTS: usize = 256;
@@ -971,7 +966,7 @@ impl LightProtocol {
}
// handle a packet with responses.
fn response(&self, peer: &PeerId, io: &IoContext, raw: Rlp) -> Result<(), Error> {
fn response(&self, peer: &PeerId, io: &IoContext, raw: UntrustedRlp) -> Result<(), Error> {
let (req_id, responses) = {
let id_guard = self.pre_verify_response(peer, &raw)?;
let responses: Vec<Response> = raw.list_at(2)?;
@@ -990,7 +985,7 @@ impl LightProtocol {
}
// handle an update of request credits parameters.
fn update_credits(&self, peer_id: &PeerId, io: &IoContext, raw: Rlp) -> Result<(), Error> {
fn update_credits(&self, peer_id: &PeerId, io: &IoContext, raw: UntrustedRlp) -> Result<(), Error> {
let peers = self.peers.read();
let peer = peers.get(peer_id).ok_or(Error::UnknownPeer)?;
@@ -1025,7 +1020,7 @@ impl LightProtocol {
}
// handle an acknowledgement of request credits update.
fn acknowledge_update(&self, peer_id: &PeerId, _io: &IoContext, _raw: Rlp) -> Result<(), Error> {
fn acknowledge_update(&self, peer_id: &PeerId, _io: &IoContext, _raw: UntrustedRlp) -> Result<(), Error> {
let peers = self.peers.read();
let peer = peers.get(peer_id).ok_or(Error::UnknownPeer)?;
let mut peer = peer.lock();
@@ -1044,7 +1039,7 @@ impl LightProtocol {
}
// Receive a set of transactions to relay.
fn relay_transactions(&self, peer: &PeerId, io: &IoContext, data: Rlp) -> Result<(), Error> {
fn relay_transactions(&self, peer: &PeerId, io: &IoContext, data: UntrustedRlp) -> Result<(), Error> {
const MAX_TRANSACTIONS: usize = 256;
let txs: Vec<_> = data.iter()
@@ -1083,34 +1078,34 @@ fn punish(peer: PeerId, io: &IoContext, e: Error) {
impl NetworkProtocolHandler for LightProtocol {
fn initialize(&self, io: &NetworkContext, _host_info: &HostInfo) {
io.register_timer(TIMEOUT, TIMEOUT_INTERVAL)
io.register_timer(TIMEOUT, TIMEOUT_INTERVAL_MS)
.expect("Error registering sync timer.");
io.register_timer(TICK_TIMEOUT, TICK_TIMEOUT_INTERVAL)
io.register_timer(TICK_TIMEOUT, TICK_TIMEOUT_INTERVAL_MS)
.expect("Error registering sync timer.");
io.register_timer(PROPAGATE_TIMEOUT, PROPAGATE_TIMEOUT_INTERVAL)
io.register_timer(PROPAGATE_TIMEOUT, PROPAGATE_TIMEOUT_INTERVAL_MS)
.expect("Error registering sync timer.");
io.register_timer(RECALCULATE_COSTS_TIMEOUT, RECALCULATE_COSTS_INTERVAL)
io.register_timer(RECALCULATE_COSTS_TIMEOUT, RECALCULATE_COSTS_INTERVAL_MS)
.expect("Error registering request timer interval token.");
}
fn read(&self, io: &NetworkContext, peer: &PeerId, packet_id: u8, data: &[u8]) {
self.handle_packet(&io, peer, packet_id, data);
self.handle_packet(io, peer, packet_id, data);
}
fn connected(&self, io: &NetworkContext, peer: &PeerId) {
self.on_connect(peer, &io);
self.on_connect(peer, io);
}
fn disconnected(&self, io: &NetworkContext, peer: &PeerId) {
self.on_disconnect(*peer, &io);
self.on_disconnect(*peer, io);
}
fn timeout(&self, io: &NetworkContext, timer: TimerToken) {
match timer {
TIMEOUT => self.timeout_check(&io),
TICK_TIMEOUT => self.tick_handlers(&io),
PROPAGATE_TIMEOUT => self.propagate_transactions(&io),
RECALCULATE_COSTS_TIMEOUT => self.begin_new_cost_period(&io),
TIMEOUT => self.timeout_check(io),
TICK_TIMEOUT => self.tick_handlers(io),
PROPAGATE_TIMEOUT => self.propagate_transactions(io),
RECALCULATE_COSTS_TIMEOUT => self.begin_new_cost_period(io),
_ => warn!(target: "pip", "received timeout on unknown token {}", timer),
}
}

View File

@@ -29,9 +29,9 @@
use request::{self, Request};
use super::error::Error;
use rlp::{Rlp, RlpStream, Decodable, Encodable, DecoderError};
use rlp::*;
use ethereum_types::U256;
use std::time::{Duration, Instant};
use time::{Duration, SteadyTime};
/// Credits value.
///
@@ -41,7 +41,7 @@ use std::time::{Duration, Instant};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Credits {
estimate: U256,
recharge_point: Instant,
recharge_point: SteadyTime,
}
impl Credits {
@@ -53,7 +53,7 @@ impl Credits {
/// a response to a request.
pub fn update_to(&mut self, value: U256) {
self.estimate = value;
self.recharge_point = Instant::now();
self.recharge_point = SteadyTime::now();
}
/// Maintain ratio to current limit against an old limit.
@@ -162,7 +162,7 @@ impl Encodable for CostTable {
}
impl Decodable for CostTable {
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
let base = rlp.val_at(0)?;
let mut headers = None;
@@ -235,30 +235,23 @@ impl FlowParams {
/// Create new flow parameters from ,
/// proportion of total capacity which should be given to a peer,
/// and stored capacity a peer can accumulate.
pub fn from_request_times<F: Fn(::request::Kind) -> Duration>(
request_time: F,
/// and number of seconds of stored capacity a peer can accumulate.
pub fn from_request_times<F: Fn(::request::Kind) -> u64>(
request_time_ns: F,
load_share: f64,
max_stored: Duration
max_stored_seconds: u64
) -> Self {
use request::Kind;
let load_share = load_share.abs();
let recharge: u64 = 100_000_000;
let max = {
let sec = max_stored.as_secs().saturating_mul(recharge);
let nanos = (max_stored.subsec_nanos() as u64).saturating_mul(recharge) / 1_000_000_000;
sec + nanos
};
let max = recharge.saturating_mul(max_stored_seconds);
let cost_for_kind = |kind| {
// how many requests we can handle per second
let rq_dur = request_time(kind);
let second_duration = {
let as_ns = rq_dur.as_secs() as f64 * 1_000_000_000f64 + rq_dur.subsec_nanos() as f64;
1_000_000_000f64 / as_ns
};
let ns = request_time_ns(kind);
let second_duration = 1_000_000_000f64 / ns as f64;
// scale by share of the load given to this peer.
let serve_per_second = second_duration * load_share;
@@ -358,19 +351,19 @@ impl FlowParams {
pub fn create_credits(&self) -> Credits {
Credits {
estimate: self.limit,
recharge_point: Instant::now(),
recharge_point: SteadyTime::now(),
}
}
/// Recharge the given credits based on time passed since last
/// update.
pub fn recharge(&self, credits: &mut Credits) {
let now = Instant::now();
let now = SteadyTime::now();
// recompute and update only in terms of full seconds elapsed
// in order to keep the estimate as an underestimate.
let elapsed = (now - credits.recharge_point).as_secs();
credits.recharge_point = credits.recharge_point + Duration::from_secs(elapsed);
let elapsed = (now - credits.recharge_point).num_seconds();
credits.recharge_point = credits.recharge_point + Duration::seconds(elapsed);
let elapsed: U256 = elapsed.into();
@@ -407,7 +400,7 @@ mod tests {
let costs = CostTable::default();
let serialized = ::rlp::encode(&costs);
let new_costs: CostTable = ::rlp::decode(&*serialized).unwrap();
let new_costs: CostTable = ::rlp::decode(&*serialized);
assert_eq!(costs, new_costs);
}
@@ -433,21 +426,21 @@ mod tests {
#[test]
fn scale_by_load_share_and_time() {
let flow_params = FlowParams::from_request_times(
|_| Duration::new(0, 10_000),
|_| 10_000,
0.05,
Duration::from_secs(60),
60,
);
let flow_params2 = FlowParams::from_request_times(
|_| Duration::new(0, 10_000),
|_| 10_000,
0.1,
Duration::from_secs(60),
60,
);
let flow_params3 = FlowParams::from_request_times(
|_| Duration::new(0, 5_000),
|_| 5_000,
0.05,
Duration::from_secs(60),
60,
);
assert_eq!(flow_params2.costs, flow_params3.costs);

View File

@@ -23,13 +23,14 @@
use std::collections::{BTreeMap, HashMap};
use std::iter::FromIterator;
use std::time::{Duration, Instant};
use request::Request;
use request::NetworkRequests as Requests;
use net::{timeout, ReqId};
use ethereum_types::U256;
use time::{Duration, SteadyTime};
// Request set entry: requests + cost.
#[derive(Debug)]
struct Entry(Requests, U256);
@@ -39,7 +40,7 @@ struct Entry(Requests, U256);
pub struct RequestSet {
counter: u64,
cumulative_cost: U256,
base: Option<Instant>,
base: Option<SteadyTime>,
ids: HashMap<ReqId, u64>,
reqs: BTreeMap<u64, Entry>,
}
@@ -58,7 +59,7 @@ impl Default for RequestSet {
impl RequestSet {
/// Push requests onto the stack.
pub fn insert(&mut self, req_id: ReqId, req: Requests, cost: U256, now: Instant) {
pub fn insert(&mut self, req_id: ReqId, req: Requests, cost: U256, now: SteadyTime) {
let counter = self.counter;
self.cumulative_cost = self.cumulative_cost + cost;
@@ -73,7 +74,7 @@ impl RequestSet {
}
/// Remove a set of requests from the stack.
pub fn remove(&mut self, req_id: &ReqId, now: Instant) -> Option<Requests> {
pub fn remove(&mut self, req_id: &ReqId, now: SteadyTime) -> Option<Requests> {
let id = match self.ids.remove(&req_id) {
Some(id) => id,
None => return None,
@@ -93,7 +94,7 @@ impl RequestSet {
/// Check for timeout against the given time. Returns true if
/// has timed out, false otherwise.
pub fn check_timeout(&self, now: Instant) -> bool {
pub fn check_timeout(&self, now: SteadyTime) -> bool {
let base = match self.base.as_ref().cloned() {
Some(base) => base,
None => return false,
@@ -127,7 +128,7 @@ impl RequestSet {
// helper to calculate timeout for a specific set of requests.
// it's a base amount + some amount per request.
fn compute_timeout(reqs: &Requests) -> Duration {
Duration::from_millis(reqs.requests().iter().fold(timeout::BASE, |tm, req| {
Duration::milliseconds(reqs.requests().iter().fold(timeout::BASE, |tm, req| {
tm + match *req {
Request::Headers(_) => timeout::HEADERS,
Request::HeaderProof(_) => timeout::HEADER_PROOF,
@@ -147,34 +148,34 @@ fn compute_timeout(reqs: &Requests) -> Duration {
mod tests {
use net::ReqId;
use request::Builder;
use std::time::{Instant, Duration};
use time::{SteadyTime, Duration};
use super::{RequestSet, compute_timeout};
#[test]
fn multi_timeout() {
let test_begin = Instant::now();
let test_begin = SteadyTime::now();
let mut req_set = RequestSet::default();
let the_req = Builder::default().build();
let req_time = compute_timeout(&the_req);
req_set.insert(ReqId(0), the_req.clone(), 0.into(), test_begin);
req_set.insert(ReqId(1), the_req, 0.into(), test_begin + Duration::from_secs(1));
req_set.insert(ReqId(1), the_req, 0.into(), test_begin + Duration::seconds(1));
assert_eq!(req_set.base, Some(test_begin));
let test_end = test_begin + req_time;
assert!(req_set.check_timeout(test_end));
req_set.remove(&ReqId(0), test_begin + Duration::from_secs(1)).unwrap();
req_set.remove(&ReqId(0), test_begin + Duration::seconds(1)).unwrap();
assert!(!req_set.check_timeout(test_end));
assert!(req_set.check_timeout(test_end + Duration::from_secs(1)));
assert!(req_set.check_timeout(test_end + Duration::seconds(1)));
}
#[test]
fn cumulative_cost() {
let the_req = Builder::default().build();
let test_begin = Instant::now();
let test_end = test_begin + Duration::from_secs(1);
let test_begin = SteadyTime::now();
let test_end = test_begin + Duration::seconds(1);
let mut req_set = RequestSet::default();
for i in 0..5 {

View File

@@ -16,7 +16,7 @@
//! Peer status and capabilities.
use rlp::{DecoderError, Encodable, Decodable, RlpStream, Rlp};
use rlp::{DecoderError, Encodable, Decodable, RlpStream, UntrustedRlp};
use ethereum_types::{H256, U256};
use super::request_credits::FlowParams;
@@ -85,7 +85,7 @@ impl Key {
// helper for decoding key-value pairs in the handshake or an announcement.
struct Parser<'a> {
pos: usize,
rlp: Rlp<'a>,
rlp: UntrustedRlp<'a>,
}
impl<'a> Parser<'a> {
@@ -97,7 +97,7 @@ impl<'a> Parser<'a> {
// expect a specific next key, and get the value's RLP.
// if the key isn't found, the position isn't advanced.
fn expect_raw(&mut self, key: Key) -> Result<Rlp<'a>, DecoderError> {
fn expect_raw(&mut self, key: Key) -> Result<UntrustedRlp<'a>, DecoderError> {
trace!(target: "les", "Expecting key {}", key.as_str());
let pre_pos = self.pos;
if let Some((k, val)) = self.get_next()? {
@@ -109,7 +109,7 @@ impl<'a> Parser<'a> {
}
// get the next key and value RLP.
fn get_next(&mut self) -> Result<Option<(Key, Rlp<'a>)>, DecoderError> {
fn get_next(&mut self) -> Result<Option<(Key, UntrustedRlp<'a>)>, DecoderError> {
while self.pos < self.rlp.item_count()? {
let pair = self.rlp.at(self.pos)?;
let k: String = pair.val_at(0)?;
@@ -208,7 +208,7 @@ impl Capabilities {
/// - chain status
/// - serving capabilities
/// - request credit parameters
pub fn parse_handshake(rlp: Rlp) -> Result<(Status, Capabilities, Option<FlowParams>), DecoderError> {
pub fn parse_handshake(rlp: UntrustedRlp) -> Result<(Status, Capabilities, Option<FlowParams>), DecoderError> {
let mut parser = Parser {
pos: 0,
rlp: rlp,
@@ -304,7 +304,7 @@ pub struct Announcement {
}
/// Parse an announcement.
pub fn parse_announcement(rlp: Rlp) -> Result<Announcement, DecoderError> {
pub fn parse_announcement(rlp: UntrustedRlp) -> Result<Announcement, DecoderError> {
let mut last_key = None;
let mut announcement = Announcement {
@@ -374,7 +374,7 @@ mod tests {
use super::*;
use super::super::request_credits::FlowParams;
use ethereum_types::{U256, H256};
use rlp::{RlpStream, Rlp};
use rlp::{RlpStream, UntrustedRlp};
#[test]
fn full_handshake() {
@@ -404,7 +404,7 @@ mod tests {
let handshake = write_handshake(&status, &capabilities, Some(&flow_params));
let (read_status, read_capabilities, read_flow)
= parse_handshake(Rlp::new(&handshake)).unwrap();
= parse_handshake(UntrustedRlp::new(&handshake)).unwrap();
assert_eq!(read_status, status);
assert_eq!(read_capabilities, capabilities);
@@ -439,7 +439,7 @@ mod tests {
let handshake = write_handshake(&status, &capabilities, Some(&flow_params));
let (read_status, read_capabilities, read_flow)
= parse_handshake(Rlp::new(&handshake)).unwrap();
= parse_handshake(UntrustedRlp::new(&handshake)).unwrap();
assert_eq!(read_status, status);
assert_eq!(read_capabilities, capabilities);
@@ -473,7 +473,7 @@ mod tests {
let handshake = write_handshake(&status, &capabilities, Some(&flow_params));
let interleaved = {
let handshake = Rlp::new(&handshake);
let handshake = UntrustedRlp::new(&handshake);
let mut stream = RlpStream::new_list(handshake.item_count().unwrap_or(0) * 3);
for item in handshake.iter() {
@@ -489,7 +489,7 @@ mod tests {
};
let (read_status, read_capabilities, read_flow)
= parse_handshake(Rlp::new(&interleaved)).unwrap();
= parse_handshake(UntrustedRlp::new(&interleaved)).unwrap();
assert_eq!(read_status, status);
assert_eq!(read_capabilities, capabilities);
@@ -510,7 +510,7 @@ mod tests {
};
let serialized = write_announcement(&announcement);
let read = parse_announcement(Rlp::new(&serialized)).unwrap();
let read = parse_announcement(UntrustedRlp::new(&serialized)).unwrap();
assert_eq!(read, announcement);
}
@@ -529,7 +529,7 @@ mod tests {
.append_raw(&encode_flag(Key::ServeHeaders), 1);
let out = stream.drain();
assert!(parse_announcement(Rlp::new(&out)).is_err());
assert!(parse_announcement(UntrustedRlp::new(&out)).is_err());
let mut stream = RlpStream::new_list(6);
stream
@@ -541,7 +541,7 @@ mod tests {
.append_raw(&encode_pair(Key::ServeStateSince, &44u64), 1);
let out = stream.drain();
assert!(parse_announcement(Rlp::new(&out)).is_ok());
assert!(parse_announcement(UntrustedRlp::new(&out)).is_ok());
}
#[test]
@@ -566,7 +566,7 @@ mod tests {
let handshake = write_handshake(&status, &capabilities, None);
let (read_status, read_capabilities, read_flow)
= parse_handshake(Rlp::new(&handshake)).unwrap();
= parse_handshake(UntrustedRlp::new(&handshake)).unwrap();
assert_eq!(read_status, status);
assert_eq!(read_capabilities, capabilities);

View File

@@ -31,11 +31,10 @@ use provider::Provider;
use request;
use request::*;
use rlp::{Rlp, RlpStream};
use rlp::*;
use ethereum_types::{H256, U256, Address};
use std::sync::Arc;
use std::time::Instant;
// helper for encoding a single request into a packet.
// panics on bad backreference.
@@ -405,7 +404,7 @@ fn get_block_receipts() {
// by the test client in that case.
let block_hashes: Vec<H256> = (0..1000)
.map(|i| provider.client.block_header(BlockId::Number(i)).unwrap().hash())
.filter(|hash| format!("{}", hash).starts_with("0xf"))
.filter(|hash| format!("{}", hash).starts_with("f"))
.take(10)
.collect();
@@ -662,8 +661,8 @@ fn id_guard() {
let mut pending_requests = RequestSet::default();
pending_requests.insert(req_id_1, req.clone(), 0.into(), Instant::now());
pending_requests.insert(req_id_2, req, 1.into(), Instant::now());
pending_requests.insert(req_id_1, req.clone(), 0.into(), ::time::SteadyTime::now());
pending_requests.insert(req_id_2, req, 1.into(), ::time::SteadyTime::now());
proto.peers.write().insert(peer_id, ::parking_lot::Mutex::new(Peer {
local_credits: flow_params.create_credits(),
@@ -671,7 +670,7 @@ fn id_guard() {
capabilities: capabilities.clone(),
remote_flow: Some((flow_params.create_credits(), (&*flow_params).clone())),
sent_head: provider.client.chain_info().best_block_hash,
last_update: Instant::now(),
last_update: ::time::SteadyTime::now(),
pending_requests: pending_requests,
failed_requests: Vec::new(),
propagated_transactions: Default::default(),
@@ -688,7 +687,7 @@ fn id_guard() {
stream.begin_list(2).append(&125usize).append(&3usize);
let packet = stream.out();
assert!(proto.response(&peer_id, &Expect::Nothing, Rlp::new(&packet)).is_err());
assert!(proto.response(&peer_id, &Expect::Nothing, UntrustedRlp::new(&packet)).is_err());
}
// next, do an unexpected response.
@@ -699,7 +698,7 @@ fn id_guard() {
stream.begin_list(0);
let packet = stream.out();
assert!(proto.response(&peer_id, &Expect::Nothing, Rlp::new(&packet)).is_err());
assert!(proto.response(&peer_id, &Expect::Nothing, UntrustedRlp::new(&packet)).is_err());
}
// lastly, do a valid (but empty) response.
@@ -710,7 +709,7 @@ fn id_guard() {
stream.begin_list(0);
let packet = stream.out();
assert!(proto.response(&peer_id, &Expect::Nothing, Rlp::new(&packet)).is_ok());
assert!(proto.response(&peer_id, &Expect::Nothing, UntrustedRlp::new(&packet)).is_ok());
}
let peers = proto.peers.read();

View File

@@ -30,7 +30,7 @@ use hash::{KECCAK_NULL_RLP, KECCAK_EMPTY, KECCAK_EMPTY_LIST_RLP, keccak};
use request::{self as net_request, IncompleteRequest, CompleteRequest, Output, OutputKind, Field};
use rlp::{RlpStream, Rlp};
use rlp::{RlpStream, UntrustedRlp};
use ethereum_types::{H256, U256, Address};
use parking_lot::Mutex;
use hashdb::HashDB;
@@ -439,7 +439,13 @@ impl CheckedRequest {
block_header
.and_then(|hdr| cache.block_body(&block_hash).map(|b| (hdr, b)))
.map(|(hdr, body)| {
Response::Body(encoded::Block::new_from_header_and_body(&hdr.view(), &body.view()))
let mut stream = RlpStream::new_list(3);
let body = body.rlp();
stream.append_raw(&hdr.rlp().as_raw(), 1);
stream.append_raw(&body.at(0).as_raw(), 1);
stream.append_raw(&body.at(1).as_raw(), 1);
Response::Body(encoded::Block::new(stream.out()))
})
}
CheckedRequest::Code(_, ref req) => {
@@ -772,22 +778,25 @@ impl Body {
pub fn check_response(&self, cache: &Mutex<::cache::Cache>, body: &encoded::Body) -> Result<encoded::Block, Error> {
// check the integrity of the the body against the header
let header = self.0.as_ref()?;
let tx_root = ::triehash::ordered_trie_root(body.transactions_rlp().iter().map(|r| r.as_raw()));
let tx_root = ::triehash::ordered_trie_root(body.rlp().at(0).iter().map(|r| r.as_raw()));
if tx_root != header.transactions_root() {
return Err(Error::WrongTrieRoot(header.transactions_root(), tx_root));
}
let uncles_hash = keccak(body.uncles_rlp().as_raw());
let uncles_hash = keccak(body.rlp().at(1).as_raw());
if uncles_hash != header.uncles_hash() {
return Err(Error::WrongHash(header.uncles_hash(), uncles_hash));
}
// concatenate the header and the body.
let block = encoded::Block::new_from_header_and_body(&header.view(), &body.view());
let mut stream = RlpStream::new_list(3);
stream.append_raw(header.rlp().as_raw(), 1);
stream.append_raw(body.rlp().at(0).as_raw(), 1);
stream.append_raw(body.rlp().at(1).as_raw(), 1);
cache.lock().insert_block_body(header.hash(), body.clone());
Ok(block)
Ok(encoded::Block::new(stream.out()))
}
}
@@ -831,7 +840,7 @@ impl Account {
match TrieDB::new(&db, &state_root).and_then(|t| t.get(&keccak(&self.address)))? {
Some(val) => {
let rlp = Rlp::new(&val);
let rlp = UntrustedRlp::new(&val);
Ok(Some(BasicAccount {
nonce: rlp.val_at(0)?,
balance: rlp.val_at(1)?,
@@ -932,7 +941,6 @@ impl Signal {
#[cfg(test)]
mod tests {
use super::*;
use std::time::Duration;
use ethereum_types::{H256, Address};
use memorydb::MemoryDB;
use parking_lot::Mutex;
@@ -940,13 +948,13 @@ mod tests {
use trie::recorder::Recorder;
use hash::keccak;
use ethcore::client::{BlockChainClient, BlockInfo, TestBlockChainClient, EachBlockWith};
use ethcore::client::{BlockChainClient, TestBlockChainClient, EachBlockWith};
use ethcore::header::Header;
use ethcore::encoded;
use ethcore::receipt::{Receipt, TransactionOutcome};
fn make_cache() -> ::cache::Cache {
::cache::Cache::new(Default::default(), Duration::from_secs(1))
::cache::Cache::new(Default::default(), ::time::Duration::seconds(1))
}
#[test]

View File

@@ -17,13 +17,14 @@
//! Tests for the on-demand service.
use cache::Cache;
use ethcore::header::Header;
use ethcore::encoded;
use ethcore::header::{Header, Seal};
use futures::Future;
use network::{PeerId, NodeId};
use net::*;
use ethereum_types::H256;
use parking_lot::Mutex;
use std::time::Duration;
use time::Duration;
use ::request::{self as basic_request, Response};
use std::sync::Arc;
@@ -87,7 +88,7 @@ struct Harness {
impl Harness {
fn create() -> Self {
let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::from_secs(60))));
let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::minutes(1))));
Harness {
service: OnDemand::new_test(cache),
}
@@ -147,7 +148,7 @@ fn single_request() {
});
let header = Header::default();
let encoded = header.encoded();
let encoded = encoded::Header::new(header.rlp(Seal::With));
let recv = harness.service.request_raw(
&Context::NoOp,
@@ -208,7 +209,7 @@ fn reassign() {
});
let header = Header::default();
let encoded = header.encoded();
let encoded = encoded::Header::new(header.rlp(Seal::With));
let recv = harness.service.request_raw(
&Context::NoOp,
@@ -256,7 +257,7 @@ fn partial_response() {
let mut hdr = Header::default();
hdr.set_number(num);
let encoded = hdr.encoded();
let encoded = encoded::Header::new(hdr.rlp(Seal::With));
(hdr, encoded)
};
@@ -315,7 +316,7 @@ fn part_bad_part_good() {
let mut hdr = Header::default();
hdr.set_number(num);
let encoded = hdr.encoded();
let encoded = encoded::Header::new(hdr.rlp(Seal::With));
(hdr, encoded)
};
@@ -412,7 +413,7 @@ fn back_references() {
});
let header = Header::default();
let encoded = header.encoded();
let encoded = encoded::Header::new(header.rlp(Seal::With));
let recv = harness.service.request_raw(
&Context::NoOp,
@@ -469,7 +470,7 @@ fn fill_from_cache() {
});
let header = Header::default();
let encoded = header.encoded();
let encoded = encoded::Header::new(header.rlp(Seal::With));
let recv = harness.service.request_raw(
&Context::NoOp,

View File

@@ -20,9 +20,9 @@
use std::sync::Arc;
use ethcore::blockchain_info::BlockChainInfo;
use ethcore::client::{BlockChainClient, ProvingBlockChainClient, ChainInfo, BlockInfo as ClientBlockInfo};
use ethcore::ids::BlockId;
use ethcore::client::{BlockChainClient, ProvingBlockChainClient};
use ethcore::encoded;
use ethcore::ids::BlockId;
use ethereum_types::H256;
use parking_lot::RwLock;
use transaction::PendingTransaction;
@@ -54,7 +54,6 @@ pub trait Provider: Send + Sync {
/// results within must adhere to the `skip` and `reverse` parameters.
fn block_headers(&self, req: request::CompleteHeadersRequest) -> Option<request::HeadersResponse> {
use request::HashOrNumber;
const MAX_HEADERS_TO_SEND: u64 = 512;
if req.max == 0 { return None }
@@ -83,12 +82,10 @@ pub trait Provider: Send + Sync {
}
};
let max = ::std::cmp::min(MAX_HEADERS_TO_SEND, req.max);
let headers: Vec<_> = (0u64..max)
.map(|x: u64| x.saturating_mul(req.skip.saturating_add(1)))
let headers: Vec<_> = (0u64..req.max as u64)
.map(|x: u64| x.saturating_mul(req.skip + 1))
.take_while(|x| if req.reverse { x < &start_num } else { best_num.saturating_sub(start_num) >= *x })
.map(|x| if req.reverse { start_num.saturating_sub(x) } else { start_num.saturating_add(x) })
.map(|x| if req.reverse { start_num - x } else { start_num + x })
.map(|x| self.block_header(BlockId::Number(x)))
.take_while(|x| x.is_some())
.flat_map(|x| x)
@@ -141,7 +138,7 @@ pub trait Provider: Send + Sync {
// Implementation of a light client data provider for a client.
impl<T: ProvingBlockChainClient + ?Sized> Provider for T {
fn chain_info(&self) -> BlockChainInfo {
ChainInfo::chain_info(self)
BlockChainClient::chain_info(self)
}
fn reorg_depth(&self, a: &H256, b: &H256) -> Option<u64> {
@@ -153,7 +150,7 @@ impl<T: ProvingBlockChainClient + ?Sized> Provider for T {
}
fn block_header(&self, id: BlockId) -> Option<encoded::Header> {
ClientBlockInfo::block_header(self, id)
BlockChainClient::block_header(self, id)
}
fn transaction_index(&self, req: request::CompleteTransactionIndexRequest)
@@ -285,9 +282,6 @@ impl<T: ProvingBlockChainClient + ?Sized> Provider for T {
fn ready_transactions(&self) -> Vec<PendingTransaction> {
BlockChainClient::ready_transactions(self)
.into_iter()
.map(|tx| tx.pending().clone())
.collect()
}
fn epoch_signal(&self, req: request::CompleteSignalRequest) -> Option<request::SignalResponse> {

View File

@@ -120,18 +120,6 @@ impl AccountTransactions {
}
}
/// Transaction import result.
pub enum ImportDestination {
/// Transaction has been imported to the current queue.
///
/// It's going to be propagated to peers.
Current,
/// Transaction has been imported to future queue.
///
/// It means it won't be propagated until the gap is filled.
Future,
}
type Listener = Box<Fn(&[H256]) + Send + Sync>;
/// Light transaction queue. See module docs for more details.
@@ -154,7 +142,7 @@ impl fmt::Debug for TransactionQueue {
impl TransactionQueue {
/// Import a pending transaction to be queued.
pub fn import(&mut self, tx: PendingTransaction) -> Result<ImportDestination, transaction::Error> {
pub fn import(&mut self, tx: PendingTransaction) -> Result<transaction::ImportResult, transaction::Error> {
let sender = tx.sender();
let hash = tx.hash();
let nonce = tx.nonce;
@@ -170,7 +158,7 @@ impl TransactionQueue {
future: BTreeMap::new(),
});
(ImportDestination::Current, vec![hash])
(transaction::ImportResult::Current, vec![hash])
}
Entry::Occupied(mut entry) => {
let acct_txs = entry.get_mut();
@@ -192,7 +180,7 @@ impl TransactionQueue {
let old = ::std::mem::replace(&mut acct_txs.current[idx], tx_info);
self.by_hash.remove(&old.hash);
(ImportDestination::Current, vec![hash])
(transaction::ImportResult::Current, vec![hash])
}
Err(idx) => {
let cur_len = acct_txs.current.len();
@@ -214,13 +202,13 @@ impl TransactionQueue {
acct_txs.future.insert(future_nonce, future);
}
(ImportDestination::Current, vec![hash])
(transaction::ImportResult::Current, vec![hash])
} else if idx == cur_len && acct_txs.current.last().map_or(false, |f| f.nonce + 1.into() != nonce) {
trace!(target: "txqueue", "Queued future transaction for {}, nonce={}", sender, nonce);
let future_nonce = nonce;
acct_txs.future.insert(future_nonce, tx_info);
(ImportDestination::Future, vec![])
(transaction::ImportResult::Future, vec![])
} else {
trace!(target: "txqueue", "Queued current transaction for {}, nonce={}", sender, nonce);
@@ -229,7 +217,7 @@ impl TransactionQueue {
let mut promoted = acct_txs.adjust_future();
promoted.insert(0, hash);
(ImportDestination::Current, promoted)
(transaction::ImportResult::Current, promoted)
}
}
}

View File

@@ -16,7 +16,7 @@
//! Light protocol request types.
use rlp::{Encodable, Decodable, DecoderError, RlpStream, Rlp};
use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp};
use ethereum_types::H256;
mod batch;
@@ -148,7 +148,7 @@ impl<T> From<T> for Field<T> {
}
impl<T: Decodable> Decodable for Field<T> {
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
match rlp.val_at::<u8>(0)? {
0 => Ok(Field::Scalar(rlp.val_at::<T>(1)?)),
1 => Ok({
@@ -224,7 +224,7 @@ impl From<u64> for HashOrNumber {
}
impl Decodable for HashOrNumber {
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
rlp.as_val::<H256>().map(HashOrNumber::Hash)
.or_else(|_| rlp.as_val().map(HashOrNumber::Number))
}
@@ -331,7 +331,7 @@ impl Request {
}
impl Decodable for Request {
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
match rlp.val_at::<Kind>(0)? {
Kind::Headers => Ok(Request::Headers(rlp.val_at(1)?)),
Kind::HeaderProof => Ok(Request::HeaderProof(rlp.val_at(1)?)),
@@ -493,7 +493,7 @@ pub enum Kind {
}
impl Decodable for Kind {
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
match rlp.as_val::<u8>()? {
0 => Ok(Kind::Headers),
1 => Ok(Kind::HeaderProof),
@@ -578,7 +578,7 @@ impl Response {
}
impl Decodable for Response {
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
match rlp.val_at::<Kind>(0)? {
Kind::Headers => Ok(Response::Headers(rlp.val_at(1)?)),
Kind::HeaderProof => Ok(Response::HeaderProof(rlp.val_at(1)?)),
@@ -673,7 +673,7 @@ pub trait ResponseLike {
pub mod header {
use super::{Field, HashOrNumber, NoSuchOutput, OutputKind, Output};
use ethcore::encoded;
use rlp::{Encodable, Decodable, DecoderError, RlpStream, Rlp};
use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp};
/// Potentially incomplete headers request.
#[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
@@ -754,7 +754,7 @@ pub mod header {
}
impl Decodable for Response {
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
use ethcore::header::Header as FullHeader;
let mut headers = Vec::new();
@@ -785,7 +785,7 @@ pub mod header {
/// Request and response for header proofs.
pub mod header_proof {
use super::{Field, NoSuchOutput, OutputKind, Output};
use rlp::{Encodable, Decodable, DecoderError, RlpStream, Rlp};
use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp};
use ethereum_types::{H256, U256};
use bytes::Bytes;
@@ -859,7 +859,7 @@ pub mod header_proof {
}
impl Decodable for Response {
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
Ok(Response {
proof: rlp.list_at(0)?,
hash: rlp.val_at(1)?,
@@ -1027,7 +1027,7 @@ pub mod block_receipts {
pub mod block_body {
use super::{Field, NoSuchOutput, OutputKind, Output};
use ethcore::encoded;
use rlp::{Encodable, Decodable, DecoderError, RlpStream, Rlp};
use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp};
use ethereum_types::H256;
/// Potentially incomplete block body request.
@@ -1092,7 +1092,7 @@ pub mod block_body {
}
impl Decodable for Response {
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
use ethcore::header::Header as FullHeader;
use transaction::UnverifiedTransaction;
@@ -1411,7 +1411,7 @@ pub mod contract_code {
pub mod execution {
use super::{Field, NoSuchOutput, OutputKind, Output};
use transaction::Action;
use rlp::{Encodable, Decodable, DecoderError, RlpStream, Rlp};
use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp};
use ethereum_types::{H256, U256, Address};
use kvdb::DBValue;
use bytes::Bytes;
@@ -1508,7 +1508,7 @@ pub mod execution {
}
impl Decodable for Response {
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
let mut items = Vec::new();
for raw_item in rlp.iter() {
let mut item = DBValue::new();
@@ -1536,7 +1536,7 @@ pub mod execution {
/// A request for epoch signal data.
pub mod epoch_signal {
use super::{Field, NoSuchOutput, OutputKind, Output};
use rlp::{Encodable, Decodable, DecoderError, RlpStream, Rlp};
use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp};
use ethereum_types::H256;
use bytes::Bytes;
@@ -1548,7 +1548,7 @@ pub mod epoch_signal {
}
impl Decodable for Incomplete {
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
Ok(Incomplete {
block_hash: rlp.val_at(0)?,
})
@@ -1617,7 +1617,7 @@ pub mod epoch_signal {
}
impl Decodable for Response {
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
Ok(Response {
signal: rlp.as_val()?,
@@ -1642,7 +1642,7 @@ mod tests {
{
// check as single value.
let bytes = ::rlp::encode(&val);
let new_val: T = ::rlp::decode(&bytes).unwrap();
let new_val: T = ::rlp::decode(&bytes);
assert_eq!(val, new_val);
// check as list containing single value.
@@ -1891,7 +1891,7 @@ mod tests {
stream.append(&100usize).append_list(&reqs);
let out = stream.out();
let rlp = Rlp::new(&out);
let rlp = UntrustedRlp::new(&out);
assert_eq!(rlp.val_at::<usize>(0).unwrap(), 100usize);
assert_eq!(rlp.list_at::<Request>(1).unwrap(), reqs);
}

View File

@@ -0,0 +1,7 @@
[package]
name = "ethcore-migrations"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
migration = { path = "../../util/migration" }

View File

@@ -14,14 +14,24 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
extern crate futures;
extern crate ethabi;
extern crate keccak_hash;
//! Database migrations.
#[macro_use]
extern crate ethabi_derive;
#[macro_use]
extern crate ethabi_contract;
extern crate migration;
mod registrar;
pub use registrar::{Registrar, RegistrarClient, Synchronous, Asynchronous};
use migration::ChangeColumns;
/// The migration from v10 to v11.
/// Adds a column for node info.
pub const TO_V11: ChangeColumns = ChangeColumns {
pre_columns: Some(6),
post_columns: Some(7),
version: 11,
};
/// The migration from v11 to v12.
/// Adds a column for light chain storage.
pub const TO_V12: ChangeColumns = ChangeColumns {
pre_columns: Some(7),
post_columns: Some(8),
version: 12,
};

View File

@@ -3,13 +3,14 @@ description = "Parity smart network connections"
homepage = "http://parity.io"
license = "GPL-3.0"
name = "node-filter"
version = "1.11.0"
version = "1.9.0"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
ethcore = { path = ".."}
ethcore-network-devp2p = { path = "../../util/network-devp2p" }
ethereum-types = "0.3"
ethcore-bytes = { path = "../../util/bytes" }
ethcore-network = { path = "../../util/network" }
ethereum-types = "0.2"
log = "0.3"
parking_lot = "0.5"
ethabi = "5.1"
@@ -20,4 +21,3 @@ lru-cache = "0.1"
[dev-dependencies]
kvdb-memorydb = { path = "../../util/kvdb-memorydb" }
ethcore-io = { path = "../../util/io" }
tempdir = "0.3"

View File

@@ -18,7 +18,8 @@
extern crate ethabi;
extern crate ethcore;
extern crate ethcore_network_devp2p as network;
extern crate ethcore_bytes as bytes;
extern crate ethcore_network as network;
extern crate ethereum_types;
extern crate lru_cache;
extern crate parking_lot;
@@ -31,8 +32,6 @@ extern crate ethabi_contract;
extern crate ethcore_io as io;
#[cfg(test)]
extern crate kvdb_memorydb;
#[cfg(test)]
extern crate tempdir;
#[macro_use]
extern crate log;
@@ -41,7 +40,8 @@ use std::sync::Weak;
use lru_cache::LruCache;
use parking_lot::Mutex;
use ethcore::client::{BlockChainClient, BlockId};
use bytes::Bytes;
use ethcore::client::{BlockChainClient, BlockId, ChainNotify};
use ethereum_types::{H256, Address};
use network::{NodeId, ConnectionFilter, ConnectionDirection};
@@ -54,7 +54,7 @@ pub struct NodeFilter {
contract: peer_set::PeerSet,
client: Weak<BlockChainClient>,
contract_address: Address,
permission_cache: Mutex<LruCache<(H256, NodeId), bool>>,
permission_cache: Mutex<LruCache<NodeId, bool>>,
}
impl NodeFilter {
@@ -62,33 +62,31 @@ impl NodeFilter {
pub fn new(client: Weak<BlockChainClient>, contract_address: Address) -> NodeFilter {
NodeFilter {
contract: peer_set::PeerSet::default(),
client,
contract_address,
client: client,
contract_address: contract_address,
permission_cache: Mutex::new(LruCache::new(MAX_CACHE_SIZE)),
}
}
/// Clear cached permissions.
pub fn clear_cache(&self) {
self.permission_cache.lock().clear();
}
}
impl ConnectionFilter for NodeFilter {
fn connection_allowed(&self, own_id: &NodeId, connecting_id: &NodeId, _direction: ConnectionDirection) -> bool {
let mut cache = self.permission_cache.lock();
if let Some(res) = cache.get_mut(connecting_id) {
return *res;
}
let client = match self.client.upgrade() {
Some(client) => client,
None => return false,
};
let block_hash = match client.block_hash(BlockId::Latest) {
Some(block_hash) => block_hash,
None => return false,
};
let key = (block_hash, *connecting_id);
let mut cache = self.permission_cache.lock();
if let Some(res) = cache.get_mut(&key) {
return *res;
}
let address = self.contract_address;
let own_low = H256::from_slice(&own_id[0..32]);
let own_high = H256::from_slice(&own_id[32..64]);
@@ -103,48 +101,59 @@ impl ConnectionFilter for NodeFilter {
false
});
cache.insert(key, allowed);
cache.insert(*connecting_id, allowed);
allowed
}
}
impl ChainNotify for NodeFilter {
fn new_blocks(&self, imported: Vec<H256>, _invalid: Vec<H256>, _enacted: Vec<H256>, _retracted: Vec<H256>, _sealed: Vec<H256>, _proposed: Vec<Bytes>, _duration: u64) {
if !imported.is_empty() {
self.clear_cache();
}
}
}
#[cfg(test)]
mod test {
use std::sync::{Arc, Weak};
use std::str::FromStr;
use ethcore::spec::Spec;
use ethcore::client::{BlockChainClient, Client, ClientConfig};
use ethcore::miner::Miner;
use ethereum_types::Address;
use network::{ConnectionDirection, ConnectionFilter, NodeId};
use io::IoChannel;
use super::NodeFilter;
use tempdir::TempDir;
/// Contract code: https://gist.github.com/arkpar/467dbcc73cbb85b0997a7a10ffa0695f
#[test]
fn node_filter() {
let contract_addr = "0000000000000000000000000000000000000005".into();
let contract_addr = Address::from_str("0000000000000000000000000000000000000005").unwrap();
let data = include_bytes!("../res/node_filter.json");
let tempdir = TempDir::new("").unwrap();
let spec = Spec::load(&tempdir.path(), &data[..]).unwrap();
let spec = Spec::load(&::std::env::temp_dir(), &data[..]).unwrap();
let client_db = Arc::new(::kvdb_memorydb::create(::ethcore::db::NUM_COLUMNS.unwrap_or(0)));
let client = Client::new(
ClientConfig::default(),
&spec,
client_db,
Arc::new(Miner::new_for_tests(&spec, None)),
Arc::new(Miner::with_spec(&spec)),
IoChannel::disconnected(),
).unwrap();
let filter = NodeFilter::new(Arc::downgrade(&client) as Weak<BlockChainClient>, contract_addr);
let self1: NodeId = "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002".into();
let self2: NodeId = "00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003".into();
let node1: NodeId = "00000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000012".into();
let node2: NodeId = "00000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000022".into();
let nodex: NodeId = "77000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into();
let self1 = NodeId::from_str("00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002").unwrap();
let self2 = NodeId::from_str("00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003").unwrap();
let node1 = NodeId::from_str("00000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000012").unwrap();
let node2 = NodeId::from_str("00000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000022").unwrap();
let nodex = NodeId::from_str("77000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap();
assert!(filter.connection_allowed(&self1, &node1, ConnectionDirection::Inbound));
assert!(filter.connection_allowed(&self1, &nodex, ConnectionDirection::Inbound));
filter.clear_cache();
assert!(filter.connection_allowed(&self2, &node1, ConnectionDirection::Inbound));
assert!(filter.connection_allowed(&self2, &node2, ConnectionDirection::Inbound));
assert!(!filter.connection_allowed(&self2, &nodex, ConnectionDirection::Inbound));
}
}

View File

@@ -1,37 +0,0 @@
[package]
description = "Parity Private Transactions"
name = "ethcore-private-tx"
version = "1.0.0"
license = "GPL-3.0"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
error-chain = { version = "0.11", default-features = false }
ethabi = "5.1"
ethabi-contract = "5.0"
ethabi-derive = "5.0"
ethcore = { path = ".." }
ethcore-bytes = { path = "../../util/bytes" }
ethcore-crypto = { path = "../crypto" }
ethcore-io = { path = "../../util/io" }
ethcore-logger = { path = "../../logger" }
ethcore-miner = { path = "../../miner" }
ethcore-transaction = { path = "../transaction" }
ethereum-types = "0.3"
ethjson = { path = "../../json" }
ethkey = { path = "../../ethkey" }
fetch = { path = "../../util/fetch" }
futures = "0.1"
keccak-hash = { path = "../../util/hash" }
log = "0.3"
parking_lot = "0.5"
patricia-trie = { path = "../../util/patricia_trie" }
rand = "0.3"
rlp = { path = "../../util/rlp" }
rlp_derive = { path = "../../util/rlp_derive" }
rustc-hex = "1.0"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
tiny-keccak = "1.3"
url = "1"

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
[{"constant": false,"inputs": [{"name": "newState","type": "bytes"},{"name": "v","type": "uint8[]"},{"name": "r","type": "bytes32[]"},{"name": "s","type": "bytes32[]"}],"name": "setState","outputs": [],"payable": false,"stateMutability": "nonpayable","type": "function"},{"constant": true,"inputs": [],"name": "code","outputs": [{"name": "","type": "bytes"}],"payable": false,"stateMutability": "view","type": "function"},{"constant": true,"inputs": [{"name": "","type": "uint256"}],"name": "validators","outputs": [{"name": "","type": "address"}],"payable": false,"stateMutability": "view","type": "function"},{"constant": true,"inputs": [],"name": "nonce","outputs": [{"name": "","type": "uint256"}],"payable": false,"stateMutability": "view","type": "function"},{"constant": true,"inputs": [],"name": "getValidators","outputs": [{"name": "","type": "address[]"}],"payable": false,"stateMutability": "view","type": "function"},{"constant": true,"inputs": [],"name": "state","outputs": [{"name": "","type": "bytes"}],"payable": false,"stateMutability": "view","type": "function"},{"inputs": [{"name": "initialValidators","type": "address[]"},{"name": "initialCode","type": "bytes"},{"name": "initialState","type": "bytes"}],"payable": false,"stateMutability": "nonpayable","type": "constructor"}]

View File

@@ -1,275 +0,0 @@
// Copyright 2015-2017 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/>.
//! Encryption providers.
use std::io::Read;
use std::str::FromStr;
use std::iter::repeat;
use std::time::{Instant, Duration};
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use parking_lot::Mutex;
use ethcore::account_provider::AccountProvider;
use ethereum_types::{H128, H256, Address};
use ethjson;
use ethkey::{Signature, Public};
use crypto;
use futures::Future;
use fetch::{Fetch, Client as FetchClient, Method, BodyReader, Request};
use bytes::{Bytes, ToPretty};
use error::{Error, ErrorKind};
use url::Url;
use super::find_account_password;
/// Initialization vector length.
const INIT_VEC_LEN: usize = 16;
/// Duration of storing retrieved keys (in ms)
const ENCRYPTION_SESSION_DURATION: u64 = 30 * 1000;
/// Trait for encryption/decryption operations.
pub trait Encryptor: Send + Sync + 'static {
/// Generate unique contract key && encrypt passed data. Encryption can only be performed once.
fn encrypt(
&self,
contract_address: &Address,
accounts: &AccountProvider,
initialisation_vector: &H128,
plain_data: &[u8],
) -> Result<Bytes, Error>;
/// Decrypt data using previously generated contract key.
fn decrypt(
&self,
contract_address: &Address,
accounts: &AccountProvider,
cypher: &[u8],
) -> Result<Bytes, Error>;
}
/// Configurtion for key server encryptor
#[derive(Default, PartialEq, Debug, Clone)]
pub struct EncryptorConfig {
/// URL to key server
pub base_url: Option<String>,
/// Key server's threshold
pub threshold: u32,
/// Account used for signing requests to key server
pub key_server_account: Option<Address>,
/// Passwords used to unlock accounts
pub passwords: Vec<String>,
}
struct EncryptionSession {
key: Bytes,
end_time: Instant,
}
/// SecretStore-based encryption/decryption operations.
pub struct SecretStoreEncryptor {
config: EncryptorConfig,
client: FetchClient,
sessions: Mutex<HashMap<Address, EncryptionSession>>,
}
impl SecretStoreEncryptor {
/// Create new encryptor
pub fn new(config: EncryptorConfig, client: FetchClient) -> Result<Self, Error> {
Ok(SecretStoreEncryptor {
config,
client,
sessions: Mutex::default(),
})
}
/// Ask secret store for key && decrypt the key.
fn retrieve_key(
&self,
url_suffix: &str,
use_post: bool,
contract_address: &Address,
accounts: &AccountProvider,
) -> Result<Bytes, Error> {
// check if the key was already cached
if let Some(key) = self.obtained_key(contract_address) {
return Ok(key);
}
let contract_address_signature = self.sign_contract_address(contract_address, accounts)?;
let requester = self.config.key_server_account.ok_or_else(|| ErrorKind::KeyServerAccountNotSet)?;
// key id in SS is H256 && we have H160 here => expand with assitional zeros
let contract_address_extended: H256 = contract_address.into();
let base_url = self.config.base_url.clone().ok_or_else(|| ErrorKind::KeyServerNotSet)?;
// prepare request url
let url = format!("{}/{}/{}{}",
base_url,
contract_address_extended.to_hex(),
contract_address_signature,
url_suffix,
);
// send HTTP request
let method = if use_post {
Method::Post
} else {
Method::Get
};
let url = Url::from_str(&url).map_err(|e| ErrorKind::Encrypt(e.to_string()))?;
let response = self.client.fetch(Request::new(url, method), Default::default()).wait()
.map_err(|e| ErrorKind::Encrypt(e.to_string()))?;
if response.is_not_found() {
bail!(ErrorKind::EncryptionKeyNotFound(*contract_address));
}
if !response.is_success() {
bail!(ErrorKind::Encrypt(response.status().canonical_reason().unwrap_or("unknown").into()));
}
// read HTTP response
let mut result = String::new();
BodyReader::new(response).read_to_string(&mut result)?;
// response is JSON string (which is, in turn, hex-encoded, encrypted Public)
let encrypted_bytes: ethjson::bytes::Bytes = result.trim_matches('\"').parse().map_err(|e| ErrorKind::Encrypt(e))?;
let password = find_account_password(&self.config.passwords, &*accounts, &requester);
// decrypt Public
let decrypted_bytes = accounts.decrypt(requester, password, &crypto::DEFAULT_MAC, &encrypted_bytes)?;
let decrypted_key = Public::from_slice(&decrypted_bytes);
// and now take x coordinate of Public as a key
let key: Bytes = (*decrypted_key)[..INIT_VEC_LEN].into();
// cache the key in the session and clear expired sessions
self.sessions.lock().insert(*contract_address, EncryptionSession{
key: key.clone(),
end_time: Instant::now() + Duration::from_millis(ENCRYPTION_SESSION_DURATION),
});
self.clean_expired_sessions();
Ok(key)
}
fn clean_expired_sessions(&self) {
let mut sessions = self.sessions.lock();
sessions.retain(|_, session| session.end_time < Instant::now());
}
fn obtained_key(&self, contract_address: &Address) -> Option<Bytes> {
let mut sessions = self.sessions.lock();
let stored_session = sessions.entry(*contract_address);
match stored_session {
Entry::Occupied(session) => {
if Instant::now() > session.get().end_time {
session.remove_entry();
None
} else {
Some(session.get().key.clone())
}
}
Entry::Vacant(_) => None,
}
}
fn sign_contract_address(&self, contract_address: &Address, accounts: &AccountProvider) -> Result<Signature, Error> {
// key id in SS is H256 && we have H160 here => expand with assitional zeros
let contract_address_extended: H256 = contract_address.into();
let key_server_account = self.config.key_server_account.ok_or_else(|| ErrorKind::KeyServerAccountNotSet)?;
let password = find_account_password(&self.config.passwords, accounts, &key_server_account);
Ok(accounts.sign(key_server_account, password, H256::from_slice(&contract_address_extended))?)
}
}
impl Encryptor for SecretStoreEncryptor {
fn encrypt(
&self,
contract_address: &Address,
accounts: &AccountProvider,
initialisation_vector: &H128,
plain_data: &[u8],
) -> Result<Bytes, Error> {
// retrieve the key, try to generate it if it doesn't exist yet
let key = match self.retrieve_key("", false, contract_address, &*accounts) {
Ok(key) => Ok(key),
Err(Error(ErrorKind::EncryptionKeyNotFound(_), _)) => {
trace!("Key for account wasnt found in sstore. Creating. Address: {:?}", contract_address);
self.retrieve_key(&format!("/{}", self.config.threshold), true, contract_address, &*accounts)
}
Err(err) => Err(err),
}?;
// encrypt data
let mut cypher = Vec::with_capacity(plain_data.len() + initialisation_vector.len());
cypher.extend(repeat(0).take(plain_data.len()));
crypto::aes::encrypt(&key, initialisation_vector, plain_data, &mut cypher);
cypher.extend_from_slice(&initialisation_vector);
Ok(cypher)
}
/// Decrypt data using previously generated contract key.
fn decrypt(
&self,
contract_address: &Address,
accounts: &AccountProvider,
cypher: &[u8],
) -> Result<Bytes, Error> {
// initialization vector takes INIT_VEC_LEN bytes
let cypher_len = cypher.len();
if cypher_len < INIT_VEC_LEN {
bail!(ErrorKind::Decrypt("Invalid cypher".into()));
}
// retrieve existing key
let key = self.retrieve_key("", false, contract_address, accounts)?;
// use symmetric decryption to decrypt document
let (cypher, iv) = cypher.split_at(cypher_len - INIT_VEC_LEN);
let mut plain_data = Vec::with_capacity(cypher_len - INIT_VEC_LEN);
plain_data.extend(repeat(0).take(cypher_len - INIT_VEC_LEN));
crypto::aes::decrypt(&key, &iv, cypher, &mut plain_data);
Ok(plain_data)
}
}
/// Dummy encryptor.
#[derive(Default)]
pub struct NoopEncryptor;
impl Encryptor for NoopEncryptor {
fn encrypt(
&self,
_contract_address: &Address,
_accounts: &AccountProvider,
_initialisation_vector: &H128,
data: &[u8],
) -> Result<Bytes, Error> {
Ok(data.to_vec())
}
fn decrypt(
&self,
_contract_address: &Address,
_accounts: &AccountProvider,
data: &[u8],
) -> Result<Bytes, Error> {
Ok(data.to_vec())
}
}

View File

@@ -1,208 +0,0 @@
// Copyright 2015-2017 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/>.
use ethereum_types::Address;
use rlp::DecoderError;
use trie::TrieError;
use ethcore::account_provider::SignError;
use ethcore::error::{Error as EthcoreError, ExecutionError};
use transaction::Error as TransactionError;
use ethkey::Error as KeyError;
error_chain! {
foreign_links {
Io(::std::io::Error) #[doc = "Error concerning the Rust standard library's IO subsystem."];
Decoder(DecoderError) #[doc = "RLP decoding error."];
Trie(TrieError) #[doc = "Error concerning TrieDBs."];
}
errors {
#[doc = "Encryption error."]
Encrypt(err: String) {
description("Encryption error"),
display("Encryption error. ({})", err),
}
#[doc = "Decryption error."]
Decrypt(err: String) {
description("Decryption error"),
display("Decryption error. ({})", err),
}
#[doc = "Address not authorized."]
NotAuthorised(address: Address) {
description("Address not authorized"),
display("Private transaction execution is not authorised for {}", address),
}
#[doc = "Transaction creates more than one contract."]
TooManyContracts {
description("Transaction creates more than one contract."),
display("Private transaction created too many contracts"),
}
#[doc = "Contract call error."]
Call(err: String) {
description("Contract call error."),
display("Contract call error. ({})", err),
}
#[doc = "State is not available."]
StatePruned {
description("State is not available."),
display("State is not available"),
}
#[doc = "State is incorrect."]
StateIncorrect {
description("State is incorrect."),
display("State is incorrect"),
}
#[doc = "Wrong private transaction type."]
BadTransactonType {
description("Wrong private transaction type."),
display("Wrong private transaction type"),
}
#[doc = "Contract does not exist or was not created."]
ContractDoesNotExist {
description("Contract does not exist or was not created."),
display("Contract does not exist or was not created"),
}
#[doc = "Reference to the client is corrupted."]
ClientIsMalformed {
description("Reference to the client is corrupted."),
display("Reference to the client is corrupted"),
}
#[doc = "Queue of private transactions for verification is full."]
QueueIsFull {
description("Queue of private transactions for verification is full."),
display("Queue of private transactions for verification is full"),
}
#[doc = "The transaction already exists in queue of private transactions."]
PrivateTransactionAlreadyImported {
description("The transaction already exists in queue of private transactions."),
display("The transaction already exists in queue of private transactions."),
}
#[doc = "The information about private transaction is not found in the store."]
PrivateTransactionNotFound {
description("The information about private transaction is not found in the store."),
display("The information about private transaction is not found in the store."),
}
#[doc = "Account for signing public transactions not set."]
SignerAccountNotSet {
description("Account for signing public transactions not set."),
display("Account for signing public transactions not set."),
}
#[doc = "Account for validating private transactions not set."]
ValidatorAccountNotSet {
description("Account for validating private transactions not set."),
display("Account for validating private transactions not set."),
}
#[doc = "Account for signing requests to key server not set."]
KeyServerAccountNotSet {
description("Account for signing requests to key server not set."),
display("Account for signing requests to key server not set."),
}
#[doc = "Encryption key is not found on key server."]
EncryptionKeyNotFound(address: Address) {
description("Encryption key is not found on key server"),
display("Encryption key is not found on key server for {}", address),
}
#[doc = "Key server URL is not set."]
KeyServerNotSet {
description("Key server URL is not set."),
display("Key server URL is not set."),
}
#[doc = "VM execution error."]
Execution(err: ExecutionError) {
description("VM execution error."),
display("VM execution error {}", err),
}
#[doc = "General signing error."]
Key(err: KeyError) {
description("General signing error."),
display("General signing error {}", err),
}
#[doc = "Account provider signing error."]
Sign(err: SignError) {
description("Account provider signing error."),
display("Account provider signing error {}", err),
}
#[doc = "Error of transactions processing."]
Transaction(err: TransactionError) {
description("Error of transactions processing."),
display("Error of transactions processing {}", err),
}
#[doc = "General ethcore error."]
Ethcore(err: EthcoreError) {
description("General ethcore error."),
display("General ethcore error {}", err),
}
}
}
impl From<SignError> for Error {
fn from(err: SignError) -> Self {
ErrorKind::Sign(err).into()
}
}
impl From<KeyError> for Error {
fn from(err: KeyError) -> Self {
ErrorKind::Key(err).into()
}
}
impl From<ExecutionError> for Error {
fn from(err: ExecutionError) -> Self {
ErrorKind::Execution(err).into()
}
}
impl From<TransactionError> for Error {
fn from(err: TransactionError) -> Self {
ErrorKind::Transaction(err).into()
}
}
impl From<EthcoreError> for Error {
fn from(err: EthcoreError) -> Self {
ErrorKind::Ethcore(err).into()
}
}
impl<E> From<Box<E>> for Error where Error: From<E> {
fn from(err: Box<E>) -> Error {
Error::from(*err)
}
}

View File

@@ -1,694 +0,0 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Private transactions module.
// Recursion limit required because of
// error_chain foreign_links.
#![recursion_limit="256"]
mod encryptor;
mod private_transactions;
mod messages;
mod error;
extern crate ethcore;
extern crate ethcore_bytes as bytes;
extern crate ethcore_crypto as crypto;
extern crate ethcore_io as io;
extern crate ethcore_miner;
extern crate ethcore_transaction as transaction;
extern crate ethabi;
extern crate ethereum_types;
extern crate ethkey;
extern crate ethjson;
extern crate fetch;
extern crate futures;
extern crate keccak_hash as hash;
extern crate parking_lot;
extern crate patricia_trie as trie;
extern crate rlp;
extern crate url;
extern crate rustc_hex;
#[macro_use]
extern crate log;
#[macro_use]
extern crate ethabi_derive;
#[macro_use]
extern crate ethabi_contract;
#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate rlp_derive;
#[cfg(test)]
extern crate rand;
#[cfg(test)]
extern crate ethcore_logger;
pub use encryptor::{Encryptor, SecretStoreEncryptor, EncryptorConfig, NoopEncryptor};
pub use private_transactions::{PrivateTransactionDesc, VerificationStore, PrivateTransactionSigningDesc, SigningStore};
pub use messages::{PrivateTransaction, SignedPrivateTransaction};
pub use error::{Error, ErrorKind};
use std::sync::{Arc, Weak};
use std::collections::{HashMap, HashSet};
use std::time::Duration;
use ethereum_types::{H128, H256, U256, Address};
use hash::keccak;
use rlp::*;
use parking_lot::{Mutex, RwLock};
use bytes::Bytes;
use ethkey::{Signature, recover, public_to_address};
use io::IoChannel;
use ethcore::executive::{Executive, TransactOptions};
use ethcore::executed::{Executed};
use transaction::{SignedTransaction, Transaction, Action, UnverifiedTransaction};
use ethcore::{contract_address as ethcore_contract_address};
use ethcore::client::{
Client, ChainNotify, ChainRoute, ChainMessageType, ClientIoMessage, BlockId, CallContract
};
use ethcore::account_provider::AccountProvider;
use ethcore::miner::{self, Miner, MinerService, pool_client::NonceCache};
use ethcore::trace::{Tracer, VMTracer};
use rustc_hex::FromHex;
// 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");
/// Initialization vector length.
const INIT_VEC_LEN: usize = 16;
/// Size of nonce cache
const NONCE_CACHE_SIZE: usize = 128;
/// Configurtion for private transaction provider
#[derive(Default, PartialEq, Debug, Clone)]
pub struct ProviderConfig {
/// Accounts that can be used for validation
pub validator_accounts: Vec<Address>,
/// Account used for signing public transactions created from private transactions
pub signer_account: Option<Address>,
/// Passwords used to unlock accounts
pub passwords: Vec<String>,
}
#[derive(Debug)]
/// Private transaction execution receipt.
pub struct Receipt {
/// Private transaction hash.
pub hash: H256,
/// Created contract address if any.
pub contract_address: Option<Address>,
/// Execution status.
pub status_code: u8,
}
/// Manager of private transactions
pub struct Provider {
encryptor: Box<Encryptor>,
validator_accounts: HashSet<Address>,
signer_account: Option<Address>,
passwords: Vec<String>,
notify: RwLock<Vec<Weak<ChainNotify>>>,
transactions_for_signing: Mutex<SigningStore>,
// TODO [ToDr] Move the Mutex/RwLock inside `VerificationStore` after refactored to `drain`.
transactions_for_verification: Mutex<VerificationStore>,
client: Arc<Client>,
miner: Arc<Miner>,
accounts: Arc<AccountProvider>,
channel: IoChannel<ClientIoMessage>,
}
#[derive(Debug)]
pub struct PrivateExecutionResult<T, V> where T: Tracer, V: VMTracer {
code: Option<Bytes>,
state: Bytes,
contract_address: Option<Address>,
result: Executed<T::Output, V::Output>,
}
impl Provider where {
/// Create a new provider.
pub fn new(
client: Arc<Client>,
miner: Arc<Miner>,
accounts: Arc<AccountProvider>,
encryptor: Box<Encryptor>,
config: ProviderConfig,
channel: IoChannel<ClientIoMessage>,
) -> Self {
Provider {
encryptor,
validator_accounts: config.validator_accounts.into_iter().collect(),
signer_account: config.signer_account,
passwords: config.passwords,
notify: RwLock::default(),
transactions_for_signing: Mutex::default(),
transactions_for_verification: Mutex::default(),
client,
miner,
accounts,
channel,
}
}
// TODO [ToDr] Don't use `ChainNotify` here!
// Better to create a separate notification type for this.
/// Adds an actor to be notified on certain events
pub fn add_notify(&self, target: Arc<ChainNotify>) {
self.notify.write().push(Arc::downgrade(&target));
}
fn notify<F>(&self, f: F) where F: Fn(&ChainNotify) {
for np in self.notify.read().iter() {
if let Some(n) = np.upgrade() {
f(&*n);
}
}
}
/// 1. Create private transaction from the signed transaction
/// 2. Executes private transaction
/// 3. Save it with state returned on prev step to the queue for signing
/// 4. Broadcast corresponding message to the chain
pub fn create_private_transaction(&self, signed_transaction: SignedTransaction) -> Result<Receipt, Error> {
trace!("Creating private transaction from regular transaction: {:?}", signed_transaction);
if self.signer_account.is_none() {
trace!("Signing account not set");
bail!(ErrorKind::SignerAccountNotSet);
}
let tx_hash = signed_transaction.hash();
match signed_transaction.action {
Action::Create => {
bail!(ErrorKind::BadTransactonType);
}
Action::Call(contract) => {
let data = signed_transaction.rlp_bytes();
let encrypted_transaction = self.encrypt(&contract, &Self::iv_from_transaction(&signed_transaction), &data)?;
let private = PrivateTransaction {
encrypted: encrypted_transaction,
contract,
};
// TODO [ToDr] Using BlockId::Latest is bad here,
// the block may change in the middle of execution
// causing really weird stuff to happen.
// We should retrieve hash and stick to that. IMHO
// best would be to change the API and only allow H256 instead of BlockID
// in private-tx to avoid such mistakes.
let contract_nonce = self.get_contract_nonce(&contract, BlockId::Latest)?;
let private_state = self.execute_private_transaction(BlockId::Latest, &signed_transaction)?;
trace!("Private transaction created, encrypted transaction: {:?}, private state: {:?}", private, private_state);
let contract_validators = self.get_validators(BlockId::Latest, &contract)?;
trace!("Required validators: {:?}", contract_validators);
let private_state_hash = self.calculate_state_hash(&private_state, contract_nonce);
trace!("Hashed effective private state for sender: {:?}", private_state_hash);
self.transactions_for_signing.lock().add_transaction(private.hash(), signed_transaction, contract_validators, private_state, contract_nonce)?;
self.broadcast_private_transaction(private.rlp_bytes().into_vec());
Ok(Receipt {
hash: tx_hash,
contract_address: None,
status_code: 0,
})
}
}
}
/// Calculate hash from united private state and contract nonce
pub fn calculate_state_hash(&self, state: &Bytes, nonce: U256) -> H256 {
let state_hash = keccak(state);
let mut state_buf = [0u8; 64];
state_buf[..32].clone_from_slice(&state_hash);
state_buf[32..].clone_from_slice(&H256::from(nonce));
keccak(&state_buf.as_ref())
}
/// Extract signed transaction from private transaction
fn extract_original_transaction(&self, private: PrivateTransaction, contract: &Address) -> Result<UnverifiedTransaction, Error> {
let encrypted_transaction = private.encrypted;
let transaction_bytes = self.decrypt(contract, &encrypted_transaction)?;
let original_transaction: UnverifiedTransaction = Rlp::new(&transaction_bytes).as_val()?;
Ok(original_transaction)
}
fn pool_client<'a>(&'a self, nonce_cache: &'a NonceCache) -> miner::pool_client::PoolClient<'a, Client> {
let engine = self.client.engine();
let refuse_service_transactions = true;
miner::pool_client::PoolClient::new(
&*self.client,
nonce_cache,
engine,
Some(&*self.accounts),
refuse_service_transactions,
)
}
/// Retrieve and verify the first available private transaction for every sender
///
/// TODO [ToDr] It seems that:
/// The 3 methods `ready_transaction,get_descriptor,remove` are always used in conjuction so most likely
/// can be replaced with a single `drain()` method instead.
/// Thanks to this we also don't really need to lock the entire verification for the time of execution.
fn process_queue(&self) -> Result<(), Error> {
let nonce_cache = NonceCache::new(NONCE_CACHE_SIZE);
let mut verification_queue = self.transactions_for_verification.lock();
let ready_transactions = verification_queue.ready_transactions(self.pool_client(&nonce_cache));
for transaction in ready_transactions {
let transaction_hash = transaction.signed().hash();
match verification_queue.private_transaction_descriptor(&transaction_hash) {
Ok(desc) => {
if !self.validator_accounts.contains(&desc.validator_account) {
trace!("Cannot find validator account in config");
bail!(ErrorKind::ValidatorAccountNotSet);
}
let account = desc.validator_account;
if let Action::Call(contract) = transaction.signed().action {
// TODO [ToDr] Usage of BlockId::Latest
let contract_nonce = self.get_contract_nonce(&contract, BlockId::Latest)?;
let private_state = self.execute_private_transaction(BlockId::Latest, transaction.signed())?;
let private_state_hash = self.calculate_state_hash(&private_state, contract_nonce);
trace!("Hashed effective private state for validator: {:?}", private_state_hash);
let password = find_account_password(&self.passwords, &*self.accounts, &account);
let signed_state = self.accounts.sign(account, password, private_state_hash)?;
let signed_private_transaction = SignedPrivateTransaction::new(desc.private_hash, signed_state, None);
trace!("Sending signature for private transaction: {:?}", signed_private_transaction);
self.broadcast_signed_private_transaction(signed_private_transaction.rlp_bytes().into_vec());
} else {
warn!("Incorrect type of action for the transaction");
}
},
Err(e) => {
warn!("Cannot retrieve descriptor for transaction with error {:?}", e);
}
}
verification_queue.remove_private_transaction(&transaction_hash);
}
Ok(())
}
fn last_required_signature(&self, desc: &PrivateTransactionSigningDesc, sign: Signature) -> Result<bool, Error> {
if desc.received_signatures.contains(&sign) {
return Ok(false);
}
let state_hash = self.calculate_state_hash(&desc.state, desc.contract_nonce);
match recover(&sign, &state_hash) {
Ok(public) => {
let sender = public_to_address(&public);
match desc.validators.contains(&sender) {
true => {
Ok(desc.received_signatures.len() + 1 == desc.validators.len())
}
false => {
trace!("Sender's state doesn't correspond to validator's");
bail!(ErrorKind::StateIncorrect);
}
}
}
Err(err) => {
trace!("Sender's state doesn't correspond to validator's, error {:?}", err);
bail!(err);
}
}
}
/// Broadcast the private transaction message to the chain
fn broadcast_private_transaction(&self, message: Bytes) {
self.notify(|notify| notify.broadcast(ChainMessageType::PrivateTransaction(message.clone())));
}
/// Broadcast signed private transaction message to the chain
fn broadcast_signed_private_transaction(&self, message: Bytes) {
self.notify(|notify| notify.broadcast(ChainMessageType::SignedPrivateTransaction(message.clone())));
}
fn iv_from_transaction(transaction: &SignedTransaction) -> H128 {
let nonce = keccak(&transaction.nonce.rlp_bytes());
let (iv, _) = nonce.split_at(INIT_VEC_LEN);
H128::from_slice(iv)
}
fn iv_from_address(contract_address: &Address) -> H128 {
let address = keccak(&contract_address.rlp_bytes());
let (iv, _) = address.split_at(INIT_VEC_LEN);
H128::from_slice(iv)
}
fn encrypt(&self, contract_address: &Address, initialisation_vector: &H128, data: &[u8]) -> Result<Bytes, Error> {
trace!("Encrypt data using key(address): {:?}", contract_address);
Ok(self.encryptor.encrypt(contract_address, &*self.accounts, initialisation_vector, data)?)
}
fn decrypt(&self, contract_address: &Address, data: &[u8]) -> Result<Bytes, Error> {
trace!("Decrypt data using key(address): {:?}", contract_address);
Ok(self.encryptor.decrypt(contract_address, &*self.accounts, data)?)
}
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)))?;
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)
}
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)))?)
}
fn snapshot_to_storage(raw: Bytes) -> HashMap<H256, H256> {
let items = raw.len() / 64;
(0..items).map(|i| {
let offset = i * 64;
let key = H256::from_slice(&raw[offset..(offset + 32)]);
let value = H256::from_slice(&raw[(offset + 32)..(offset + 64)]);
(key, value)
}).collect()
}
fn snapshot_from_storage(storage: &HashMap<H256, H256>) -> Bytes {
let mut raw = Vec::with_capacity(storage.len() * 64);
for (key, value) in storage {
raw.extend_from_slice(key);
raw.extend_from_slice(value);
};
raw
}
pub fn execute_private<T, V>(&self, transaction: &SignedTransaction, options: TransactOptions<T, V>, block: BlockId) -> Result<PrivateExecutionResult<T, V>, Error>
where
T: Tracer,
V: VMTracer,
{
let mut env_info = self.client.env_info(block).ok_or(ErrorKind::StatePruned)?;
env_info.gas_limit = transaction.gas;
let mut state = self.client.state_at(block).ok_or(ErrorKind::StatePruned)?;
// TODO: in case of BlockId::Latest these need to operate on the same state
let contract_address = match transaction.action {
Action::Call(ref contract_address) => {
let contract_code = Arc::new(self.get_decrypted_code(contract_address, block)?);
let contract_state = self.get_decrypted_state(contract_address, block)?;
trace!("Patching contract at {:?}, code: {:?}, state: {:?}", contract_address, contract_code, contract_state);
state.patch_account(contract_address, contract_code, Self::snapshot_to_storage(contract_state))?;
Some(*contract_address)
},
Action::Create => None,
};
let engine = self.client.engine();
let contract_address = contract_address.or({
let sender = transaction.sender();
let nonce = state.nonce(&sender)?;
let (new_address, _) = ethcore_contract_address(engine.create_address_scheme(env_info.number), &sender, &nonce, &transaction.data);
Some(new_address)
});
let result = Executive::new(&mut state, &env_info, engine.machine()).transact_virtual(transaction, options)?;
let (encrypted_code, encrypted_storage) = match contract_address {
None => bail!(ErrorKind::ContractDoesNotExist),
Some(address) => {
let (code, storage) = state.into_account(&address)?;
let enc_code = match code {
Some(c) => Some(self.encrypt(&address, &Self::iv_from_address(&address), &c)?),
None => None,
};
(enc_code, self.encrypt(&address, &Self::iv_from_transaction(transaction), &Self::snapshot_from_storage(&storage))?)
},
};
trace!("Private contract executed. code: {:?}, state: {:?}, result: {:?}", encrypted_code, encrypted_storage, result.output);
Ok(PrivateExecutionResult {
code: encrypted_code,
state: encrypted_storage,
contract_address,
result,
})
}
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)
}
fn generate_set_state_call(signatures: &[Signature], storage: Bytes) -> Bytes {
let private = private::PrivateContract::default();
private.functions().set_state().input(
storage,
signatures.iter().map(|s| {
let mut v: [u8; 32] = [0; 32];
v[31] = s.v();
v
}).collect::<Vec<[u8; 32]>>(),
signatures.iter().map(|s| s.r()).collect::<Vec<&[u8]>>(),
signatures.iter().map(|s| s.s()).collect::<Vec<&[u8]>>()
)
}
/// Returns the key from the key server associated with the contract
pub fn contract_key_id(&self, contract_address: &Address) -> Result<H256, Error> {
//current solution uses contract address extended with 0 as id
let contract_address_extended: H256 = contract_address.into();
Ok(H256::from_slice(&contract_address_extended))
}
/// Create encrypted public contract deployment transaction.
pub fn public_creation_transaction(&self, block: BlockId, source: &SignedTransaction, validators: &[Address], gas_price: U256) -> Result<(Transaction, Option<Address>), Error> {
if let Action::Call(_) = source.action {
bail!(ErrorKind::BadTransactonType);
}
let sender = source.sender();
let state = self.client.state_at(block).ok_or(ErrorKind::StatePruned)?;
let nonce = state.nonce(&sender)?;
let executed = self.execute_private(source, TransactOptions::with_no_tracing(), block)?;
let gas: u64 = 650000 +
validators.len() as u64 * 30000 +
executed.code.as_ref().map_or(0, |c| c.len() as u64) * 8000 +
executed.state.len() as u64 * 8000;
Ok((Transaction {
nonce: nonce,
action: Action::Create,
gas: gas.into(),
gas_price: gas_price,
value: source.value,
data: Self::generate_constructor(validators, executed.code.unwrap_or_default(), executed.state)
},
executed.contract_address))
}
/// Create encrypted public contract deployment transaction. Returns updated encrypted state.
pub fn execute_private_transaction(&self, block: BlockId, source: &SignedTransaction) -> Result<Bytes, Error> {
if let Action::Create = source.action {
bail!(ErrorKind::BadTransactonType);
}
let result = self.execute_private(source, TransactOptions::with_no_tracing(), block)?;
Ok(result.state)
}
/// Create encrypted public transaction from private transaction.
pub fn public_transaction(&self, state: Bytes, source: &SignedTransaction, signatures: &[Signature], nonce: U256, gas_price: U256) -> Result<Transaction, Error> {
let gas: u64 = 650000 + state.len() as u64 * 8000 + signatures.len() as u64 * 50000;
Ok(Transaction {
nonce: nonce,
action: source.action.clone(),
gas: gas.into(),
gas_price: gas_price,
value: 0.into(),
data: Self::generate_set_state_call(signatures, state)
})
}
/// Call into private contract.
pub fn private_call(&self, block: BlockId, transaction: &SignedTransaction) -> Result<Executed, Error> {
let result = self.execute_private(transaction, TransactOptions::with_no_tracing(), block)?;
Ok(result.result)
}
/// 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)))?)
}
}
pub trait Importer {
/// Process received private transaction
fn import_private_transaction(&self, _rlp: &[u8]) -> Result<(), Error>;
/// Add signed private transaction into the store
///
/// Creates corresponding public transaction if last required signature collected and sends it to the chain
fn import_signed_private_transaction(&self, _rlp: &[u8]) -> Result<(), Error>;
}
// TODO [ToDr] Offload more heavy stuff to the IoService thread.
// It seems that a lot of heavy work (verification) is done in this thread anyway
// it might actually make sense to decouple it from clientService and just use dedicated thread
// for both verification and execution.
impl Importer for Arc<Provider> {
fn import_private_transaction(&self, rlp: &[u8]) -> Result<(), Error> {
trace!("Private transaction received");
let private_tx: PrivateTransaction = Rlp::new(rlp).as_val()?;
let contract = private_tx.contract;
let contract_validators = self.get_validators(BlockId::Latest, &contract)?;
let validation_account = contract_validators
.iter()
.find(|address| self.validator_accounts.contains(address));
match validation_account {
None => {
// TODO [ToDr] This still seems a bit invalid, imho we should still import the transaction to the pool.
// Importing to pool verifies correctness and nonce; here we are just blindly forwarding.
//
// Not for verification, broadcast further to peers
self.broadcast_private_transaction(rlp.into());
return Ok(());
},
Some(&validation_account) => {
let hash = private_tx.hash();
trace!("Private transaction taken for verification");
let original_tx = self.extract_original_transaction(private_tx, &contract)?;
trace!("Validating transaction: {:?}", original_tx);
// Verify with the first account available
trace!("The following account will be used for verification: {:?}", validation_account);
let nonce_cache = NonceCache::new(NONCE_CACHE_SIZE);
self.transactions_for_verification.lock().add_transaction(
original_tx,
contract,
validation_account,
hash,
self.pool_client(&nonce_cache),
)?;
let provider = Arc::downgrade(self);
self.channel.send(ClientIoMessage::execute(move |_| {
if let Some(provider) = provider.upgrade() {
if let Err(e) = provider.process_queue() {
debug!("Unable to process the queue: {}", e);
}
}
})).map_err(|_| ErrorKind::ClientIsMalformed.into())
}
}
}
fn import_signed_private_transaction(&self, rlp: &[u8]) -> Result<(), Error> {
let tx: SignedPrivateTransaction = Rlp::new(rlp).as_val()?;
trace!("Signature for private transaction received: {:?}", tx);
let private_hash = tx.private_transaction_hash();
let desc = match self.transactions_for_signing.lock().get(&private_hash) {
None => {
// TODO [ToDr] Verification (we can't just blindly forward every transaction)
// Not our transaction, broadcast further to peers
self.broadcast_signed_private_transaction(rlp.into());
return Ok(());
},
Some(desc) => desc,
};
let last = self.last_required_signature(&desc, tx.signature())?;
if last {
let mut signatures = desc.received_signatures.clone();
signatures.push(tx.signature());
let rsv: Vec<Signature> = signatures.into_iter().map(|sign| sign.into_electrum().into()).collect();
//Create public transaction
let public_tx = self.public_transaction(
desc.state.clone(),
&desc.original_transaction,
&rsv,
desc.original_transaction.nonce,
desc.original_transaction.gas_price
)?;
trace!("Last required signature received, public transaction created: {:?}", public_tx);
//Sign and add it to the queue
let chain_id = desc.original_transaction.chain_id();
let hash = public_tx.hash(chain_id);
let signer_account = self.signer_account.ok_or_else(|| ErrorKind::SignerAccountNotSet)?;
let password = find_account_password(&self.passwords, &*self.accounts, &signer_account);
let signature = self.accounts.sign(signer_account, password, hash)?;
let signed = SignedTransaction::new(public_tx.with_signature(signature, chain_id))?;
match self.miner.import_own_transaction(&*self.client, signed.into()) {
Ok(_) => trace!("Public transaction added to queue"),
Err(err) => {
trace!("Failed to add transaction to queue, error: {:?}", err);
bail!(err);
}
}
//Remove from store for signing
match self.transactions_for_signing.lock().remove(&private_hash) {
Ok(_) => {}
Err(err) => {
trace!("Failed to remove transaction from signing store, error: {:?}", err);
bail!(err);
}
}
} else {
//Add signature to the store
match self.transactions_for_signing.lock().add_signature(&private_hash, tx.signature()) {
Ok(_) => trace!("Signature stored for private transaction"),
Err(err) => {
trace!("Failed to add signature to signing store, error: {:?}", err);
bail!(err);
}
}
}
Ok(())
}
}
/// Try to unlock account using stored password, return found password if any
fn find_account_password(passwords: &Vec<String>, account_provider: &AccountProvider, account: &Address) -> Option<String> {
for password in passwords {
if let Ok(true) = account_provider.test_password(account, password) {
return Some(password.clone());
}
}
None
}
impl ChainNotify for Provider {
fn new_blocks(&self, imported: Vec<H256>, _invalid: Vec<H256>, _route: ChainRoute, _sealed: Vec<H256>, _proposed: Vec<Bytes>, _duration: Duration) {
if !imported.is_empty() {
trace!("New blocks imported, try to prune the queue");
if let Err(err) = self.process_queue() {
trace!("Cannot prune private transactions queue. error: {:?}", err);
}
}
}
}

View File

@@ -1,76 +0,0 @@
// Copyright 2015-2017 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/>.
use ethereum_types::{H256, U256, Address};
use bytes::Bytes;
use hash::keccak;
use rlp::Encodable;
use ethkey::Signature;
use transaction::signature::{add_chain_replay_protection, check_replay_protection};
/// Message with private transaction encrypted
#[derive(Default, Debug, Clone, PartialEq, RlpEncodable, RlpDecodable, Eq)]
pub struct PrivateTransaction {
/// Encrypted data
pub encrypted: Bytes,
/// Address of the contract
pub contract: Address,
}
impl PrivateTransaction {
/// Compute hash on private transaction
pub fn hash(&self) -> H256 {
keccak(&*self.rlp_bytes())
}
}
/// Message about private transaction's signing
#[derive(Default, Debug, Clone, PartialEq, RlpEncodable, RlpDecodable, Eq)]
pub struct SignedPrivateTransaction {
/// Hash of the corresponding private transaction
private_transaction_hash: H256,
/// Signature of the validator
/// The V field of the signature
v: u64,
/// The R field of the signature
r: U256,
/// The S field of the signature
s: U256,
}
impl SignedPrivateTransaction {
/// Construct a signed private transaction message
pub fn new(private_transaction_hash: H256, sig: Signature, chain_id: Option<u64>) -> Self {
SignedPrivateTransaction {
private_transaction_hash: private_transaction_hash,
r: sig.r().into(),
s: sig.s().into(),
v: add_chain_replay_protection(sig.v() as u64, chain_id),
}
}
pub fn standard_v(&self) -> u8 { check_replay_protection(self.v) }
/// Construct a signature object from the sig.
pub fn signature(&self) -> Signature {
Signature::from_rsv(&self.r.into(), &self.s.into(), self.standard_v())
}
/// Get the hash of of the original transaction.
pub fn private_transaction_hash(&self) -> H256 {
self.private_transaction_hash
}
}

View File

@@ -1,208 +0,0 @@
// Copyright 2015-2017 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/>.
use std::sync::Arc;
use std::collections::{HashMap, HashSet};
use bytes::Bytes;
use ethcore_miner::pool;
use ethereum_types::{H256, U256, Address};
use ethkey::Signature;
use transaction::{UnverifiedTransaction, SignedTransaction};
use error::{Error, ErrorKind};
/// Maximum length for private transactions queues.
const MAX_QUEUE_LEN: usize = 8312;
/// Desriptor for private transaction stored in queue for verification
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct PrivateTransactionDesc {
/// Hash of the private transaction
pub private_hash: H256,
/// Contract's address used in private transaction
pub contract: Address,
/// Address that should be used for verification
pub validator_account: Address,
}
/// Storage for private transactions for verification
pub struct VerificationStore {
/// Descriptors for private transactions in queue for verification with key - hash of the original transaction
descriptors: HashMap<H256, PrivateTransactionDesc>,
/// Queue with transactions for verification
///
/// TODO [ToDr] Might actually be better to use `txpool` directly and:
/// 1. Store descriptors inside `VerifiedTransaction`
/// 2. Use custom `ready` implementation to only fetch one transaction per sender.
/// 3. Get rid of passing dummy `block_number` and `timestamp`
transactions: pool::TransactionQueue,
}
impl Default for VerificationStore {
fn default() -> Self {
VerificationStore {
descriptors: Default::default(),
transactions: pool::TransactionQueue::new(
pool::Options {
max_count: MAX_QUEUE_LEN,
max_per_sender: MAX_QUEUE_LEN / 10,
max_mem_usage: 8 * 1024 * 1024,
},
pool::verifier::Options {
// TODO [ToDr] This should probably be based on some real values?
minimal_gas_price: 0.into(),
block_gas_limit: 8_000_000.into(),
tx_gas_limit: U256::max_value(),
},
pool::PrioritizationStrategy::GasPriceOnly,
)
}
}
}
impl VerificationStore {
/// Adds private transaction for verification into the store
pub fn add_transaction<C: pool::client::Client>(
&mut self,
transaction: UnverifiedTransaction,
contract: Address,
validator_account: Address,
private_hash: H256,
client: C,
) -> Result<(), Error> {
if self.descriptors.len() > MAX_QUEUE_LEN {
bail!(ErrorKind::QueueIsFull);
}
let transaction_hash = transaction.hash();
if self.descriptors.get(&transaction_hash).is_some() {
bail!(ErrorKind::PrivateTransactionAlreadyImported);
}
let results = self.transactions.import(
client,
vec![pool::verifier::Transaction::Unverified(transaction)],
);
// Verify that transaction was imported
results.into_iter()
.next()
.expect("One transaction inserted; one result returned; qed")?;
self.descriptors.insert(transaction_hash, PrivateTransactionDesc {
private_hash,
contract,
validator_account,
});
Ok(())
}
/// Returns transactions ready for verification
/// Returns only one transaction per sender because several cannot be verified in a row without verification from other peers
pub fn ready_transactions<C: pool::client::NonceClient>(&self, client: C) -> Vec<Arc<pool::VerifiedTransaction>> {
// We never store PendingTransactions and we don't use internal cache,
// so we don't need to provide real block number of timestamp here
let block_number = 0;
let timestamp = 0;
let nonce_cap = None;
self.transactions.collect_pending(client, block_number, timestamp, nonce_cap, |transactions| {
// take only one transaction per sender
let mut senders = HashSet::with_capacity(self.descriptors.len());
transactions.filter(move |tx| senders.insert(tx.signed().sender())).collect()
})
}
/// Returns descriptor of the corresponding private transaction
pub fn private_transaction_descriptor(&self, transaction_hash: &H256) -> Result<&PrivateTransactionDesc, Error> {
self.descriptors.get(transaction_hash).ok_or(ErrorKind::PrivateTransactionNotFound.into())
}
/// Remove transaction from the queue for verification
pub fn remove_private_transaction(&mut self, transaction_hash: &H256) {
self.descriptors.remove(transaction_hash);
self.transactions.remove(&[*transaction_hash], true);
}
}
/// Desriptor for private transaction stored in queue for signing
#[derive(Debug, Clone)]
pub struct PrivateTransactionSigningDesc {
/// Original unsigned transaction
pub original_transaction: SignedTransaction,
/// Supposed validators from the contract
pub validators: Vec<Address>,
/// Already obtained signatures
pub received_signatures: Vec<Signature>,
/// State after transaction execution to compare further with received from validators
pub state: Bytes,
/// Build-in nonce of the contract
pub contract_nonce: U256,
}
/// Storage for private transactions for signing
#[derive(Default)]
pub struct SigningStore {
/// Transactions and descriptors for signing
transactions: HashMap<H256, PrivateTransactionSigningDesc>,
}
impl SigningStore {
/// Adds new private transaction into the store for signing
pub fn add_transaction(
&mut self,
private_hash: H256,
transaction: SignedTransaction,
validators: Vec<Address>,
state: Bytes,
contract_nonce: U256,
) -> Result<(), Error> {
if self.transactions.len() > MAX_QUEUE_LEN {
bail!(ErrorKind::QueueIsFull);
}
self.transactions.insert(private_hash, PrivateTransactionSigningDesc {
original_transaction: transaction.clone(),
validators: validators.clone(),
received_signatures: Vec::new(),
state,
contract_nonce,
});
Ok(())
}
/// Get copy of private transaction's description from the storage
pub fn get(&self, private_hash: &H256) -> Option<PrivateTransactionSigningDesc> {
self.transactions.get(private_hash).cloned()
}
/// Removes desc from the store (after verification is completed)
pub fn remove(&mut self, private_hash: &H256) -> Result<(), Error> {
self.transactions.remove(private_hash);
Ok(())
}
/// Adds received signature for the stored private transaction
pub fn add_signature(&mut self, private_hash: &H256, signature: Signature) -> Result<(), Error> {
let desc = self.transactions.get_mut(private_hash).ok_or_else(|| ErrorKind::PrivateTransactionNotFound)?;
if !desc.received_signatures.contains(&signature) {
desc.received_signatures.push(signature);
}
Ok(())
}
}

View File

@@ -1,146 +0,0 @@
// Copyright 2015-2017 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/>.
//! Contract for private transactions tests.
extern crate rustc_hex;
extern crate ethcore;
extern crate ethkey;
extern crate keccak_hash as hash;
extern crate ethcore_io;
extern crate ethcore_logger;
extern crate ethcore_private_tx;
extern crate ethcore_transaction;
#[macro_use]
extern crate log;
use std::sync::Arc;
use rustc_hex::FromHex;
use ethcore::CreateContractAddress;
use ethcore::account_provider::AccountProvider;
use ethcore::client::BlockChainClient;
use ethcore::client::BlockId;
use ethcore::executive::{contract_address};
use ethcore::miner::Miner;
use ethcore::test_helpers::{generate_dummy_client, push_block_with_transactions};
use ethcore_transaction::{Transaction, Action};
use ethkey::{Secret, KeyPair, Signature};
use hash::keccak;
use ethcore_private_tx::{NoopEncryptor, Provider, ProviderConfig};
#[test]
fn private_contract() {
// This uses a simple private contract: contract Test1 { bytes32 public x; function setX(bytes32 _x) { x = _x; } }
ethcore_logger::init_log();
let client = generate_dummy_client(0);
let chain_id = client.signing_chain_id();
let key1 = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000011")).unwrap();
let _key2 = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000012")).unwrap();
let key3 = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000013")).unwrap();
let key4 = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000014")).unwrap();
let ap = Arc::new(AccountProvider::transient_provider());
ap.insert_account(key1.secret().clone(), "").unwrap();
ap.insert_account(key3.secret().clone(), "").unwrap();
ap.insert_account(key4.secret().clone(), "").unwrap();
let config = ProviderConfig{
validator_accounts: vec![key3.address(), key4.address()],
signer_account: None,
passwords: vec!["".into()],
};
let io = ethcore_io::IoChannel::disconnected();
let miner = Arc::new(Miner::new_for_tests(&::ethcore::spec::Spec::new_test(), None));
let pm = Arc::new(Provider::new(
client.clone(),
miner,
ap.clone(),
Box::new(NoopEncryptor::default()),
config,
io,
));
let (address, _) = contract_address(CreateContractAddress::FromSenderAndNonce, &key1.address(), &0.into(), &[]);
trace!("Creating private contract");
let private_contract_test = "6060604052341561000f57600080fd5b60d88061001d6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630c55699c146046578063bc64b76d14607457600080fd5b3415605057600080fd5b60566098565b60405180826000191660001916815260200191505060405180910390f35b3415607e57600080fd5b6096600480803560001916906020019091905050609e565b005b60005481565b8060008160001916905550505600a165627a7a723058206acbdf4b15ca4c2d43e1b1879b830451a34f1e9d02ff1f2f394d8d857e79d2080029".from_hex().unwrap();
let mut private_create_tx = Transaction::default();
private_create_tx.action = Action::Create;
private_create_tx.data = private_contract_test;
private_create_tx.gas = 200000.into();
let private_create_tx_signed = private_create_tx.sign(&key1.secret(), None);
let validators = vec![key3.address(), key4.address()];
let (public_tx, _) = pm.public_creation_transaction(BlockId::Latest, &private_create_tx_signed, &validators, 0.into()).unwrap();
let public_tx = public_tx.sign(&key1.secret(), chain_id);
trace!("Transaction created. Pushing block");
push_block_with_transactions(&client, &[public_tx]);
trace!("Modifying private state");
let mut private_tx = Transaction::default();
private_tx.action = Action::Call(address.clone());
private_tx.data = "bc64b76d2a00000000000000000000000000000000000000000000000000000000000000".from_hex().unwrap(); //setX(42)
private_tx.gas = 120000.into();
private_tx.nonce = 1.into();
let private_tx = private_tx.sign(&key1.secret(), None);
let private_contract_nonce = pm.get_contract_nonce(&address, BlockId::Latest).unwrap();
let private_state = pm.execute_private_transaction(BlockId::Latest, &private_tx).unwrap();
let nonced_state_hash = pm.calculate_state_hash(&private_state, private_contract_nonce);
let signatures: Vec<_> = [&key3, &key4].iter().map(|k|
Signature::from(::ethkey::sign(&k.secret(), &nonced_state_hash).unwrap().into_electrum())).collect();
let public_tx = pm.public_transaction(private_state, &private_tx, &signatures, 1.into(), 0.into()).unwrap();
let public_tx = public_tx.sign(&key1.secret(), chain_id);
push_block_with_transactions(&client, &[public_tx]);
trace!("Querying private state");
let mut query_tx = Transaction::default();
query_tx.action = Action::Call(address.clone());
query_tx.data = "0c55699c".from_hex().unwrap(); // getX
query_tx.gas = 50000.into();
query_tx.nonce = 2.into();
let query_tx = query_tx.sign(&key1.secret(), chain_id);
let result = pm.private_call(BlockId::Latest, &query_tx).unwrap();
assert_eq!(&result.output[..], &("2a00000000000000000000000000000000000000000000000000000000000000".from_hex().unwrap()[..]));
assert_eq!(pm.get_validators(BlockId::Latest, &address).unwrap(), validators);
// Now try modification with just one signature
trace!("Modifying private state");
let mut private_tx = Transaction::default();
private_tx.action = Action::Call(address.clone());
private_tx.data = "bc64b76d2b00000000000000000000000000000000000000000000000000000000000000".from_hex().unwrap(); //setX(43)
private_tx.gas = 120000.into();
private_tx.nonce = 2.into();
let private_tx = private_tx.sign(&key1.secret(), None);
let private_state = pm.execute_private_transaction(BlockId::Latest, &private_tx).unwrap();
let private_state_hash = keccak(&private_state);
let signatures: Vec<_> = [&key4].iter().map(|k|
Signature::from(::ethkey::sign(&k.secret(), &private_state_hash).unwrap().into_electrum())).collect();
let public_tx = pm.public_transaction(private_state, &private_tx, &signatures, 2.into(), 0.into()).unwrap();
let public_tx = public_tx.sign(&key1.secret(), chain_id);
push_block_with_transactions(&client, &[public_tx]);
trace!("Querying private state");
let mut query_tx = Transaction::default();
query_tx.action = Action::Call(address.clone());
query_tx.data = "0c55699c".from_hex().unwrap(); // getX
query_tx.gas = 50000.into();
query_tx.nonce = 3.into();
let query_tx = query_tx.sign(&key1.secret(), chain_id);
let result = pm.private_call(BlockId::Latest, &query_tx).unwrap();
assert_eq!(result.output, "2a00000000000000000000000000000000000000000000000000000000000000".from_hex().unwrap());
}

View File

@@ -1,61 +0,0 @@
{
"name": "TestAuthorityRoundBlockRewardContract",
"engine": {
"authorityRound": {
"params": {
"stepDuration": 1,
"startStep": 2,
"validators": {
"list": [
"0x7d577a597b2742b498cb5cf0c26cdcd726d39e6e",
"0x82a978b3f5962a5b0957d9ee9eef472ee55b42f1"
]
},
"immediateTransitions": true,
"emptyStepsTransition": "1",
"maximumEmptySteps": "2",
"blockRewardContractAddress": "0x0000000000000000000000000000000000000042"
}
}
},
"params": {
"gasLimitBoundDivisor": "0x0400",
"accountStartNonce": "0x0",
"maximumExtraDataSize": "0x20",
"minGasLimit": "0x1388",
"networkID" : "0x69",
"eip140Transition": "0x0",
"eip211Transition": "0x0",
"eip214Transition": "0x0",
"eip658Transition": "0x0"
},
"genesis": {
"seal": {
"authorityRound": {
"step": "0x0",
"signature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
}
},
"difficulty": "0x20000",
"author": "0x0000000000000000000000000000000000000000",
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x",
"gasLimit": "0x222222"
},
"accounts": {
"0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
"0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
"0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
"0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
"0000000000000000000000000000000000000005": { "balance": "1", "builtin": { "name": "modexp", "activate_at": 0, "pricing": { "modexp": { "divisor": 20 } } } },
"0000000000000000000000000000000000000006": { "balance": "1", "builtin": { "name": "alt_bn128_add", "activate_at": 0, "pricing": { "linear": { "base": 500, "word": 0 } } } },
"0000000000000000000000000000000000000007": { "balance": "1", "builtin": { "name": "alt_bn128_mul", "activate_at": 0, "pricing": { "linear": { "base": 40000, "word": 0 } } } },
"0000000000000000000000000000000000000008": { "balance": "1", "builtin": { "name": "alt_bn128_pairing", "activate_at": 0, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } },
"9cce34f7ab185c7aba1b7c8140d620b4bda941d6": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" },
"0000000000000000000000000000000000000042": {
"balance": "1",
"constructor": "6060604052341561000f57600080fd5b6102b88061001e6000396000f300606060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063f91c289814610046575b600080fd5b341561005157600080fd5b610086600480803590602001908201803590602001919091929080359060200190820180359060200191909192905050610125565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156100cd5780820151818401526020810190506100b2565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561010f5780820151818401526020810190506100f4565b5050505090500194505050505060405180910390f35b61012d610264565b610135610278565b61013d610278565b600073fffffffffffffffffffffffffffffffffffffffe73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561018d57600080fd5b85859050888890501415156101a157600080fd5b878790506040518059106101b25750595b90808252806020026020018201604052509150600090505b815181101561021d5785858281811015156101e157fe5b9050602002013561ffff166103e80161ffff16828281518110151561020257fe5b906020019060200201818152505080806001019150506101ca565b878783828280806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050915090915093509350505094509492505050565b602060405190810160405280600081525090565b6020604051908101604052806000815250905600a165627a7a723058201da0f164e75517fb8baf51f030b904032cb748334938e7386f63025bfb23f3de0029"
}
}
}

View File

@@ -1,29 +0,0 @@
[
{
"constant": false,
"inputs": [
{
"name": "benefactors",
"type": "address[]"
},
{
"name": "kind",
"type": "uint16[]"
}
],
"name": "reward",
"outputs": [
{
"name": "",
"type": "address[]"
},
{
"name": "",
"type": "uint256[]"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
}
]

View File

@@ -57,8 +57,7 @@
"enode://814920f1ec9510aa9ea1c8f79d8b6e6a462045f09caa2ae4055b0f34f7416fca6facd3dd45f1cf1673c0209e0503f02776b8ff94020e98b6679a0dc561b4eba0@104.154.136.117:30303",
"enode://72e445f4e89c0f476d404bc40478b0df83a5b500d2d2e850e08eb1af0cd464ab86db6160d0fde64bd77d5f0d33507ae19035671b3c74fec126d6e28787669740@104.198.71.200:30303",
"enode://39abab9d2a41f53298c0c9dc6bbca57b0840c3ba9dccf42aa27316addc1b7e56ade32a0a9f7f52d6c5db4fe74d8824bcedfeaecf1a4e533cacb71cf8100a9442@144.76.238.49:30303",
"enode://f50e675a34f471af2438b921914b5f06499c7438f3146f6b8936f1faeb50b8a91d0d0c24fb05a66f05865cd58c24da3e664d0def806172ddd0d4c5bdbf37747e@144.76.238.49:30306",
"enode://83b33409349ffa25e150555f7b4f8deebc68f3d34d782129dc3c8ba07b880c209310a4191e1725f2f6bef59bce9452d821111eaa786deab08a7e6551fca41f4f@159.89.223.6:30303"
"enode://f50e675a34f471af2438b921914b5f06499c7438f3146f6b8936f1faeb50b8a91d0d0c24fb05a66f05865cd58c24da3e664d0def806172ddd0d4c5bdbf37747e@144.76.238.49:30306"
],
"accounts": {
"0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },

View File

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

View File

@@ -51,14 +51,21 @@
"gasLimit": "0x1388"
},
"nodes": [
"enode://0d88e242aa0b01ee306ca43e956174677c96ec8eba4197f4d8be6fd7d4f2e57731e95d533b88229b66eb1a44399d870e99b7a4fe6547c8c80cdf00407a986e14@94.130.237.158:30303",
"enode://4be9e419d3efb0214faf3ef1794a0c33ebbd7633ece734a0a956faa166fefc496b2692a2a485adc66af805e461ba3e12f8d3941ec207e56bb9f3d3626787a705@94.130.237.158:60606",
"enode://98b48cc7149326d00a57994ad55014a095a3e5cd4f0144cd7b034fb667d8e8017082bd90047d72c4403798b8ece11a33bd2e344d6500faba30889ebcfa5316fa@172.104.163.204:30303",
"enode://834246cc2a7584df29ccdcf3b5366f118a0e291264980376769e809665a02c4caf0d68c43eecf8390dbeaf861823b05583807af0a62542a1f3f717046b958a76@45.77.106.33:30303",
"enode://d1373d7187a20d695220fafb5746a289786bad92469d6bbe800f07572f8f444479f507cfcb8fcd8f5bee5dd44efb6185df4a1e4f1a7170408ada9876ef5b3fe4@178.79.189.58:30303",
"enode://d8059dcb137cb52b8960ca82613eeba1d121105572decd8f1d3ea22b09070645eeab548d2a3cd2914f206e1331c7870bd2bd5a231ebac6b3d4886ec3b8e627e5@173.212.216.105:30303",
"enode://5a89c8664d29a321fd4cb1b55b0f0be832ce376b5e7feb14a2073fdbd9bd7b7394169ed289dd991112b42ecfb74ea36e436bc72a1c99dcdb50d96eaf3b0ed254@213.136.91.42:30303",
"enode://9215ad77bd081e35013cb42a8ceadff9d8e94a78fcc680dff1752a54e7484badff0904e331c4b40a68be593782e55acfd800f076d22f9d2832e8483733ade149@213.14.82.125:30303",
"enode://07913818dafbadf44d4fc796fa414ec1d720ecfb087eff37efbe7134556658e92351559de788fa319c291e40b915cc26d902069d03bd935553d4efa688bdbbf8@45.32.19.37:30303",
"enode://645a59b6e6e20ed8864767a1d0c731f89ae276ed4e04c4f10becce655532d95cbe1bc9e2da3f13a6564f9ca8fe46fab2781a380b3a89148bccac883d6068f684@45.77.159.123:30303",
"enode://7c2f43b2e7fded9469917311574d267427e62cd12e1864effd15f31c1246e4e955463d843acaa37309693a515df7986cb6d160b7e85a4ca2779a798a72d90850@108.61.194.191:30303",
"enode://5dd35866da95aea15211fb1f98684f6e8c4e355e6aa3cc17585680ed53fa164477b8c52cb6ca4b24ec4d80f3d48ff9212b53feb131d825c7945a3abaaf02d24d@178.79.189.58:60606",
"enode://6c585c18024eb902ca093278af73b04863ac904caabc39ac2920c23532307c572ad92afd828a990c980d272b1f26307f2409cc97aec3ff9fe866732cae49a8c2@144.217.163.224:31337",
"enode://edd90c4cc64528802ad52fd127d80b641ff80fd43fa5292fb111c8bd2914482dffee288fd1b0d26440c6b2c669b10a53cbcd37c895ba0d6194110e100a965b2d@188.166.179.159:30303",
"enode://d19783546438e8bfc11a35457ff1f47871a2ce4801b9b2dbe7606321a9ce29007305497eb8c98d7ae9dc5a913ee5533c3691b1080f7066697c4276e6140d2eac@45.77.47.184:30303",
"enode://13ed57615447bc9bf1da4e28249369babc00d2530d6c103c12350453e469a5e90cbcdb787c436977467f5864be6e64f2520180fc60b841c8c3daf84df9450190@104.207.152.17:30303",
"enode://59c228a6a0939a0b53edf6924bc7bd1384652dc1da0777495acd0707975f485f54a77c7b2dcbeece9340a43ccd9c7ea70f0cdfe48936537d238b50e5cb5dc0b2@45.77.233.0:30303",
"enode://9d960373335c1cc38ca696dea8f2893e2a071c8f21524f21e8aae22be032acc3b67797b1d21e866f9d832943ae7d9555b8466c6ab34f473d21e547114952df37@213.32.53.183:30303"
],
"accounts": {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -24,7 +24,7 @@
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x",
"gasLimit": "0x7A1200"
"gasLimit": "0x5B8D80"
},
"accounts": {
"0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },

View File

@@ -1,20 +0,0 @@
[package]
name = "ethcore-service"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
ansi_term = "0.10"
error-chain = { version = "0.11", default-features = false }
ethcore = { path = ".." }
ethcore-io = { path = "../../util/io" }
ethcore-private-tx = { path = "../private-tx" }
ethcore-sync = { path = "../sync" }
kvdb = { path = "../../util/kvdb" }
log = "0.3"
stop-guard = { path = "../../util/stop-guard" }
trace-time = { path = "../../util/trace-time" }
[dev-dependencies]
tempdir = "0.3"
kvdb-rocksdb = { path = "../../util/kvdb-rocksdb" }

View File

@@ -1,30 +0,0 @@
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use ethcore;
use io;
use ethcore_private_tx;
error_chain! {
links {
PrivateTransactions(ethcore_private_tx::Error, ethcore_private_tx::ErrorKind);
}
foreign_links {
Ethcore(ethcore::error::Error);
IoError(io::IoError);
}
}

View File

@@ -1,44 +0,0 @@
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
extern crate ansi_term;
extern crate ethcore;
extern crate ethcore_io as io;
extern crate ethcore_private_tx;
extern crate ethcore_sync as sync;
extern crate kvdb;
extern crate stop_guard;
#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate log;
#[macro_use]
extern crate trace_time;
#[cfg(test)]
extern crate tempdir;
mod error;
mod service;
#[cfg(test)]
extern crate kvdb_rocksdb;
pub use error::{Error, ErrorKind};
pub use service::{ClientService, PrivateTxService};

17
ethcore/src/account_provider/mod.rs Normal file → Executable file
View File

@@ -66,6 +66,8 @@ pub enum SignError {
Hardware(HardwareError),
/// Low-level error from store
SStore(SSError),
/// Inappropriate chain
InappropriateChain,
}
impl fmt::Display for SignError {
@@ -75,6 +77,7 @@ impl fmt::Display for SignError {
SignError::NotFound => write!(f, "Account does not exist"),
SignError::Hardware(ref e) => write!(f, "{}", e),
SignError::SStore(ref e) => write!(f, "{}", e),
SignError::InappropriateChain => write!(f, "Inappropriate chain"),
}
}
}
@@ -272,8 +275,8 @@ impl AccountProvider {
}
/// Checks whether an account with a given address is present.
pub fn has_account(&self, address: Address) -> bool {
self.sstore.account_ref(&address).is_ok() && !self.blacklisted_accounts.contains(&address)
pub fn has_account(&self, address: Address) -> Result<bool, Error> {
Ok(self.sstore.account_ref(&address).is_ok() && !self.blacklisted_accounts.contains(&address))
}
/// Returns addresses of all accounts.
@@ -638,8 +641,8 @@ impl AccountProvider {
}
/// Unlocks account temporarily with a timeout.
pub fn unlock_account_timed(&self, account: Address, password: String, duration: Duration) -> Result<(), Error> {
self.unlock_account(account, password, Unlock::Timed(Instant::now() + duration))
pub fn unlock_account_timed(&self, account: Address, password: String, duration_ms: u32) -> Result<(), Error> {
self.unlock_account(account, password, Unlock::Timed(Instant::now() + Duration::from_millis(duration_ms as u64)))
}
/// Checks if given account is unlocked
@@ -834,7 +837,7 @@ impl AccountProvider {
#[cfg(test)]
mod tests {
use super::{AccountProvider, Unlock, DappId};
use std::time::{Duration, Instant};
use std::time::Instant;
use ethstore::ethkey::{Generator, Random, Address};
use ethstore::{StoreAccountRef, Derivation};
use ethereum_types::H256;
@@ -938,8 +941,8 @@ mod tests {
let kp = Random.generate().unwrap();
let ap = AccountProvider::transient_provider();
assert!(ap.insert_account(kp.secret().clone(), "test").is_ok());
assert!(ap.unlock_account_timed(kp.address(), "test1".into(), Duration::from_secs(60)).is_err());
assert!(ap.unlock_account_timed(kp.address(), "test".into(), Duration::from_secs(60)).is_ok());
assert!(ap.unlock_account_timed(kp.address(), "test1".into(), 60000).is_err());
assert!(ap.unlock_account_timed(kp.address(), "test".into(), 60000).is_ok());
assert!(ap.sign(kp.address(), None, Default::default()).is_ok());
ap.unlocked.write().get_mut(&StoreAccountRef::root(kp.address())).unwrap().unlock = Unlock::Timed(Instant::now());
assert!(ap.sign(kp.address(), None, Default::default()).is_err());

View File

@@ -22,7 +22,7 @@ use std::collections::HashSet;
use hash::{keccak, KECCAK_NULL_RLP, KECCAK_EMPTY_LIST_RLP};
use triehash::ordered_trie_root;
use rlp::{Rlp, RlpStream, Encodable, Decodable, DecoderError, encode_list};
use rlp::{UntrustedRlp, RlpStream, Encodable, Decodable, DecoderError};
use ethereum_types::{H256, U256, Address, Bloom};
use bytes::Bytes;
use unexpected::{Mismatch, OutOfBounds};
@@ -31,7 +31,7 @@ use vm::{EnvInfo, LastHashes};
use engines::EthEngine;
use error::{Error, BlockError};
use factory::Factories;
use header::Header;
use header::{Header, Seal};
use receipt::{Receipt, TransactionOutcome};
use state::State;
use state_db::StateDB;
@@ -54,21 +54,22 @@ pub struct Block {
impl Block {
/// Returns true if the given bytes form a valid encoding of a block in RLP.
pub fn is_good(b: &[u8]) -> bool {
Rlp::new(b).as_val::<Block>().is_ok()
UntrustedRlp::new(b).as_val::<Block>().is_ok()
}
/// Get the RLP-encoding of the block with the seal.
pub fn rlp_bytes(&self) -> Bytes {
/// Get the RLP-encoding of the block with or without the seal.
pub fn rlp_bytes(&self, seal: Seal) -> Bytes {
let mut block_rlp = RlpStream::new_list(3);
block_rlp.append(&self.header);
self.header.stream_rlp(&mut block_rlp, seal);
block_rlp.append_list(&self.transactions);
block_rlp.append_list(&self.uncles);
block_rlp.out()
}
}
impl Decodable for Block {
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
if rlp.as_raw().len() != rlp.payload_info()?.total() {
return Err(DecoderError::RlpIsTooBig);
}
@@ -267,8 +268,9 @@ impl<'x> OpenBlock<'x> {
r.block.header.set_parent_hash(parent.hash());
r.block.header.set_number(number);
r.block.header.set_author(author);
r.block.header.set_timestamp(engine.open_block_header_timestamp(parent.timestamp()));
r.block.header.set_timestamp_now(parent.timestamp());
r.block.header.set_extra_data(extra_data);
r.block.header.note_dirty();
let gas_floor_target = cmp::max(gas_range_target.0, engine.params().min_gas_limit);
let gas_ceil_target = cmp::max(gas_range_target.1, gas_floor_target);
@@ -282,14 +284,38 @@ impl<'x> OpenBlock<'x> {
Ok(r)
}
/// Alter the timestamp of the block.
pub fn set_timestamp(&mut self, timestamp: u64) {
self.block.header.set_timestamp(timestamp);
}
/// Alter the author for the block.
pub fn set_author(&mut self, author: Address) { self.block.header.set_author(author); }
/// Removes block gas limit.
pub fn remove_gas_limit(&mut self) {
self.block.header.set_gas_limit(U256::max_value());
/// Alter the timestamp of the block.
pub fn set_timestamp(&mut self, timestamp: u64) { self.block.header.set_timestamp(timestamp); }
/// Alter the difficulty for the block.
pub fn set_difficulty(&mut self, a: U256) { self.block.header.set_difficulty(a); }
/// Alter the gas limit for the block.
pub fn set_gas_limit(&mut self, a: U256) { self.block.header.set_gas_limit(a); }
/// Alter the gas limit for the block.
pub fn set_gas_used(&mut self, a: U256) { self.block.header.set_gas_used(a); }
/// Alter the uncles hash the block.
pub fn set_uncles_hash(&mut self, h: H256) { self.block.header.set_uncles_hash(h); }
/// Alter transactions root for the block.
pub fn set_transactions_root(&mut self, h: H256) { self.block.header.set_transactions_root(h); }
/// Alter the receipts root for the block.
pub fn set_receipts_root(&mut self, h: H256) { self.block.header.set_receipts_root(h); }
/// Alter the extra_data for the block.
pub fn set_extra_data(&mut self, extra_data: Bytes) -> Result<(), BlockError> {
if extra_data.len() > self.engine.maximum_extra_data_size() {
Err(BlockError::ExtraDataOutOfBounds(OutOfBounds{min: None, max: Some(self.engine.maximum_extra_data_size()), found: extra_data.len()}))
} else {
self.block.header.set_extra_data(extra_data);
Ok(())
}
}
/// Add an uncle to the block, if possible.
@@ -321,65 +347,40 @@ impl<'x> OpenBlock<'x> {
/// If valid, it will be executed, and archived together with the receipt.
pub fn push_transaction(&mut self, t: SignedTransaction, h: Option<H256>) -> Result<&Receipt, Error> {
if self.block.transactions_set.contains(&t.hash()) {
return Err(TransactionError::AlreadyImported.into());
return Err(From::from(TransactionError::AlreadyImported));
}
let env_info = self.env_info();
let outcome = self.block.state.apply(&env_info, self.engine.machine(), &t, self.block.traces.is_enabled())?;
self.block.transactions_set.insert(h.unwrap_or_else(||t.hash()));
self.block.transactions.push(t.into());
if let Tracing::Enabled(ref mut traces) = self.block.traces {
traces.push(outcome.trace.into());
}
self.block.receipts.push(outcome.receipt);
Ok(self.block.receipts.last().expect("receipt just pushed; qed"))
}
/// Push transactions onto the block.
#[cfg(not(feature = "slow-blocks"))]
fn push_transactions(&mut self, transactions: Vec<SignedTransaction>) -> Result<(), Error> {
for t in transactions {
self.push_transaction(t, None)?;
}
Ok(())
}
/// Push transactions onto the block.
#[cfg(feature = "slow-blocks")]
fn push_transactions(&mut self, transactions: Vec<SignedTransaction>) -> Result<(), Error> {
use std::time;
let slow_tx = option_env!("SLOW_TX_DURATION").and_then(|v| v.parse().ok()).unwrap_or(100);
for t in transactions {
let hash = t.hash();
let start = time::Instant::now();
self.push_transaction(t, None)?;
let took = start.elapsed();
let took_ms = took.as_secs() * 1000 + took.subsec_nanos() as u64 / 1000000;
if took > time::Duration::from_millis(slow_tx) {
warn!("Heavy ({} ms) transaction in block {:?}: {:?}", took_ms, block.header().number(), hash);
// info!("env_info says gas_used={}", env_info.gas_used);
match self.block.state.apply(&env_info, self.engine.machine(), &t, self.block.traces.is_enabled()) {
Ok(outcome) => {
self.block.transactions_set.insert(h.unwrap_or_else(||t.hash()));
self.block.transactions.push(t.into());
let t = outcome.trace;
if let Tracing::Enabled(ref mut traces) = self.block.traces {
traces.push(t.into());
}
self.block.receipts.push(outcome.receipt);
Ok(self.block.receipts.last().expect("receipt just pushed; qed"))
}
debug!(target: "tx", "Transaction {:?} took: {} ms", hash, took_ms);
Err(x) => Err(From::from(x))
}
}
Ok(())
/// Push transactions onto the block.
pub fn push_transactions(&mut self, transactions: &[SignedTransaction]) -> Result<(), Error> {
push_transactions(self, transactions)
}
/// Populate self from a header.
fn populate_from(&mut self, header: &Header) {
self.block.header.set_difficulty(*header.difficulty());
self.block.header.set_gas_limit(*header.gas_limit());
self.block.header.set_timestamp(header.timestamp());
self.block.header.set_author(*header.author());
self.block.header.set_uncles_hash(*header.uncles_hash());
self.block.header.set_transactions_root(*header.transactions_root());
// TODO: that's horrible. set only for backwards compatibility
if header.extra_data().len() > self.engine.maximum_extra_data_size() {
warn!("Couldn't set extradata. Ignoring.");
} else {
self.block.header.set_extra_data(header.extra_data().clone());
}
pub fn populate_from(&mut self, header: &Header) {
self.set_difficulty(*header.difficulty());
self.set_gas_limit(*header.gas_limit());
self.set_timestamp(header.timestamp());
self.set_author(header.author().clone());
self.set_extra_data(header.extra_data().clone()).unwrap_or_else(|e| warn!("Couldn't set extradata: {}. Ignoring.", e));
self.set_uncles_hash(header.uncles_hash().clone());
self.set_transactions_root(header.transactions_root().clone());
}
/// Turn this into a `ClosedBlock`.
@@ -396,20 +397,17 @@ impl<'x> OpenBlock<'x> {
warn!("Encountered error on state commit: {}", e);
}
s.block.header.set_transactions_root(ordered_trie_root(s.block.transactions.iter().map(|e| e.rlp_bytes())));
let uncle_bytes = encode_list(&s.block.uncles).into_vec();
let uncle_bytes = s.block.uncles.iter().fold(RlpStream::new_list(s.block.uncles.len()), |mut s, u| {s.append_raw(&u.rlp(Seal::With), 1); s} ).out();
s.block.header.set_uncles_hash(keccak(&uncle_bytes));
s.block.header.set_state_root(s.block.state.root().clone());
s.block.header.set_receipts_root(ordered_trie_root(s.block.receipts.iter().map(|r| r.rlp_bytes())));
s.block.header.set_log_bloom(s.block.receipts.iter().fold(Bloom::zero(), |mut b, r| {
b.accrue_bloom(&r.log_bloom);
b
}));
s.block.header.set_gas_used(s.block.receipts.last().map_or_else(U256::zero, |r| r.gas_used));
s.block.header.set_log_bloom(s.block.receipts.iter().fold(Bloom::zero(), |mut b, r| {b = &b | &r.log_bloom; b})); //TODO: use |= operator
s.block.header.set_gas_used(s.block.receipts.last().map_or(U256::zero(), |r| r.gas_used));
ClosedBlock {
block: s.block,
uncle_bytes,
unclosed_state,
uncle_bytes: uncle_bytes,
unclosed_state: unclosed_state,
}
}
@@ -424,11 +422,10 @@ impl<'x> OpenBlock<'x> {
if let Err(e) = s.block.state.commit() {
warn!("Encountered error on state commit: {}", e);
}
if s.block.header.transactions_root().is_zero() || s.block.header.transactions_root() == &KECCAK_NULL_RLP {
s.block.header.set_transactions_root(ordered_trie_root(s.block.transactions.iter().map(|e| e.rlp_bytes())));
}
let uncle_bytes = encode_list(&s.block.uncles).into_vec();
let uncle_bytes = s.block.uncles.iter().fold(RlpStream::new_list(s.block.uncles.len()), |mut s, u| {s.append_raw(&u.rlp(Seal::With), 1); s} ).out();
if s.block.header.uncles_hash().is_zero() || s.block.header.uncles_hash() == &KECCAK_EMPTY_LIST_RLP {
s.block.header.set_uncles_hash(keccak(&uncle_bytes));
}
@@ -437,15 +434,12 @@ impl<'x> OpenBlock<'x> {
}
s.block.header.set_state_root(s.block.state.root().clone());
s.block.header.set_log_bloom(s.block.receipts.iter().fold(Bloom::zero(), |mut b, r| {
b.accrue_bloom(&r.log_bloom);
b
}));
s.block.header.set_gas_used(s.block.receipts.last().map_or_else(U256::zero, |r| r.gas_used));
s.block.header.set_log_bloom(s.block.receipts.iter().fold(Bloom::zero(), |mut b, r| {b = &b | &r.log_bloom; b})); //TODO: use |= operator
s.block.header.set_gas_used(s.block.receipts.last().map_or(U256::zero(), |r| r.gas_used));
LockedBlock {
block: s.block,
uncle_bytes,
uncle_bytes: uncle_bytes,
}
}
@@ -468,7 +462,7 @@ impl<'x> IsBlock for LockedBlock {
impl ClosedBlock {
/// Get the hash of the header without seal arguments.
pub fn hash(&self) -> H256 { self.header().bare_hash() }
pub fn hash(&self) -> H256 { self.header().rlp_keccak(Seal::Without) }
/// Turn this into a `LockedBlock`, unable to be reopened again.
pub fn lock(self) -> LockedBlock {
@@ -491,26 +485,8 @@ impl ClosedBlock {
}
impl LockedBlock {
/// Removes outcomes from receipts and updates the receipt root.
///
/// This is done after the block is enacted for historical reasons.
/// We allow inconsistency in receipts for some chains if `validate_receipts_transition`
/// is set to non-zero value, so the check only happens if we detect
/// unmatching root first and then fall back to striped receipts.
pub fn strip_receipts_outcomes(&mut self) {
for receipt in &mut self.block.receipts {
receipt.outcome = TransactionOutcome::Unknown;
}
self.block.header.set_receipts_root(
ordered_trie_root(self.block.receipts.iter().map(|r| r.rlp_bytes()))
);
// compute hash and cache it.
self.block.header.compute_hash();
}
/// Get the hash of the header without seal arguments.
pub fn hash(&self) -> H256 { self.header().bare_hash() }
pub fn hash(&self) -> H256 { self.header().rlp_keccak(Seal::Without) }
/// Provide a valid seal in order to turn this into a `SealedBlock`.
///
@@ -523,7 +499,6 @@ impl LockedBlock {
Mismatch { expected: expected_seal_fields, found: seal.len() }));
}
s.block.header.set_seal(seal);
s.block.header.compute_hash();
Ok(SealedBlock { block: s.block, uncle_bytes: s.uncle_bytes })
}
@@ -537,7 +512,6 @@ impl LockedBlock {
) -> Result<SealedBlock, (Error, LockedBlock)> {
let mut s = self;
s.block.header.set_seal(seal);
s.block.header.compute_hash();
// TODO: passing state context to avoid engines owning it?
match engine.verify_local_seal(&s.block.header) {
@@ -545,6 +519,16 @@ impl LockedBlock {
_ => Ok(SealedBlock { block: s.block, uncle_bytes: s.uncle_bytes }),
}
}
/// Remove state root from transaction receipts to make them EIP-98 compatible.
pub fn strip_receipts(self) -> LockedBlock {
let mut block = self;
for receipt in &mut block.block.receipts {
receipt.outcome = TransactionOutcome::Unknown;
}
block.block.header.set_receipts_root(ordered_trie_root(block.block.receipts.iter().map(|r| r.rlp_bytes())));
block
}
}
impl Drain for LockedBlock {
@@ -558,7 +542,7 @@ impl SealedBlock {
/// Get the RLP-encoding of the block.
pub fn rlp_bytes(&self) -> Bytes {
let mut block_rlp = RlpStream::new_list(3);
block_rlp.append(&self.block.header);
self.block.header.stream_rlp(&mut block_rlp, Seal::With);
block_rlp.append_list(&self.block.transactions);
block_rlp.append_raw(&self.uncle_bytes, 1);
block_rlp.out()
@@ -577,10 +561,10 @@ impl IsBlock for SealedBlock {
}
/// Enact the block given by block header, transactions and uncles
fn enact(
header: Header,
transactions: Vec<SignedTransaction>,
uncles: Vec<Header>,
pub fn enact(
header: &Header,
transactions: &[SignedTransaction],
uncles: &[Header],
engine: &EthEngine,
tracing: bool,
db: StateDB,
@@ -610,19 +594,48 @@ fn enact(
is_epoch_begin,
)?;
b.populate_from(&header);
b.populate_from(header);
b.push_transactions(transactions)?;
for u in uncles {
b.push_uncle(u)?;
b.push_uncle(u.clone())?;
}
Ok(b.close_and_lock())
}
#[inline]
#[cfg(not(feature = "slow-blocks"))]
fn push_transactions(block: &mut OpenBlock, transactions: &[SignedTransaction]) -> Result<(), Error> {
for t in transactions {
block.push_transaction(t.clone(), None)?;
}
Ok(())
}
#[cfg(feature = "slow-blocks")]
fn push_transactions(block: &mut OpenBlock, transactions: &[SignedTransaction]) -> Result<(), Error> {
use std::time;
let slow_tx = option_env!("SLOW_TX_DURATION").and_then(|v| v.parse().ok()).unwrap_or(100);
for t in transactions {
let hash = t.hash();
let start = time::Instant::now();
block.push_transaction(t.clone(), None)?;
let took = start.elapsed();
let took_ms = took.as_secs() * 1000 + took.subsec_nanos() as u64 / 1000000;
if took > time::Duration::from_millis(slow_tx) {
warn!("Heavy ({} ms) transaction in block {:?}: {:?}", took_ms, block.header().number(), hash);
}
debug!(target: "tx", "Transaction {:?} took: {} ms", hash, took_ms);
}
Ok(())
}
// TODO [ToDr] Pass `PreverifiedBlock` by move, this will avoid unecessary allocation
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header
pub fn enact_verified(
block: PreverifiedBlock,
block: &PreverifiedBlock,
engine: &EthEngine,
tracing: bool,
db: StateDB,
@@ -631,12 +644,12 @@ pub fn enact_verified(
factories: Factories,
is_epoch_begin: bool,
) -> Result<LockedBlock, Error> {
let view = view!(BlockView, &block.bytes);
let view = BlockView::new(&block.bytes);
enact(
block.header,
block.transactions,
view.uncles(),
&block.header,
&block.transactions,
&view.uncles(),
engine,
tracing,
db,
@@ -649,7 +662,7 @@ pub fn enact_verified(
#[cfg(test)]
mod tests {
use test_helpers::get_temp_state_db;
use tests::helpers::*;
use super::*;
use engines::EthEngine;
use vm::LastHashes;
@@ -672,7 +685,7 @@ mod tests {
last_hashes: Arc<LastHashes>,
factories: Factories,
) -> Result<LockedBlock, Error> {
let block = view!(BlockView, block_bytes);
let block = BlockView::new(block_bytes);
let header = block.header();
let transactions: Result<Vec<_>, Error> = block
.transactions()
@@ -704,7 +717,7 @@ mod tests {
)?;
b.populate_from(&header);
b.push_transactions(transactions)?;
b.push_transactions(&transactions)?;
for u in &block.uncles() {
b.push_uncle(u.clone())?;
@@ -723,7 +736,7 @@ mod tests {
last_hashes: Arc<LastHashes>,
factories: Factories,
) -> Result<SealedBlock, Error> {
let header = view!(BlockView, block_bytes).header_view();
let header = BlockView::new(block_bytes).header_view();
Ok(enact_bytes(block_bytes, engine, tracing, db, parent, last_hashes, factories)?.seal(engine, header.seal())?)
}
@@ -789,7 +802,7 @@ mod tests {
let bytes = e.rlp_bytes();
assert_eq!(bytes, orig_bytes);
let uncles = view!(BlockView, &bytes).uncles();
let uncles = BlockView::new(&bytes).uncles();
assert_eq!(uncles[1].extra_data(), b"uncle2");
let db = e.drain();
@@ -797,4 +810,3 @@ mod tests {
assert!(orig_db.journal_db().keys().iter().filter(|k| orig_db.journal_db().get(k.0) != db.journal_db().get(k.0)).next() == None);
}
}

View File

@@ -15,23 +15,22 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use ethereum_types::{H256, U256};
use bytes::Bytes;
use header::BlockNumber;
use encoded;
use header::{Header, BlockNumber};
/// Contains information on a best block that is specific to the consensus engine.
///
/// For GHOST fork-choice rule it would typically describe the block with highest
/// combined difficulty (usually the block with the highest block number).
///
/// Sometimes refered as 'latest block'.
/// Best block info.
#[derive(Default)]
pub struct BestBlock {
/// Best block decoded header.
pub header: Header,
/// Best block uncompressed bytes.
pub block: encoded::Block,
/// Best block hash.
pub hash: H256,
/// Best block number.
pub number: BlockNumber,
/// Best block timestamp.
pub timestamp: u64,
/// Best block total difficulty.
pub total_difficulty: U256,
/// Best block uncompressed bytes
pub block: Bytes,
}
/// Best ancient block info. If the blockchain has a gap this keeps track of where it starts.

View File

@@ -25,11 +25,11 @@ use heapsize::HeapSizeOf;
use ethereum_types::{H256, Bloom, U256};
use parking_lot::{Mutex, RwLock};
use bytes::Bytes;
use rlp::RlpStream;
use rlp::*;
use rlp_compress::{compress, decompress, blocks_swapper};
use header::*;
use transaction::*;
use views::{BlockView, HeaderView};
use views::*;
use log_entry::{LogEntry, LocalizedLogEntry};
use receipt::Receipt;
use blooms::{BloomGroup, GroupPosition};
@@ -96,6 +96,11 @@ pub trait BlockProvider {
/// Get receipts of block with given hash.
fn block_receipts(&self, hash: &H256) -> Option<BlockReceipts>;
/// Get the partial-header of a block.
fn block_header(&self, hash: &H256) -> Option<Header> {
self.block_header_data(hash).map(|header| header.decode())
}
/// Get the header RLP of a block.
fn block_header_data(&self, hash: &H256) -> Option<encoded::Header>;
@@ -116,7 +121,7 @@ pub trait BlockProvider {
/// Get the number of given block's hash.
fn block_number(&self, hash: &H256) -> Option<BlockNumber> {
self.block_header_data(hash).map(|header| header.number())
self.block_details(hash).map(|details| details.number)
}
/// Get transaction with given transaction hash.
@@ -145,8 +150,8 @@ pub trait BlockProvider {
}
/// Returns the header of the genesis block.
fn genesis_header(&self) -> encoded::Header {
self.block_header_data(&self.genesis_hash())
fn genesis_header(&self) -> Header {
self.block_header(&self.genesis_hash())
.expect("Genesis header always stored; qed")
}
@@ -194,8 +199,8 @@ pub struct BlockChain {
first_block: Option<H256>,
// block cache
block_headers: RwLock<HashMap<H256, encoded::Header>>,
block_bodies: RwLock<HashMap<H256, encoded::Body>>,
block_headers: RwLock<HashMap<H256, Bytes>>,
block_bodies: RwLock<HashMap<H256, Bytes>>,
// extra caches
block_details: RwLock<HashMap<H256, BlockDetails>>,
@@ -235,9 +240,17 @@ impl BlockProvider for BlockChain {
/// Get raw block data
fn block(&self, hash: &H256) -> Option<encoded::Block> {
let header = self.block_header_data(hash)?;
let body = self.block_body(hash)?;
Some(encoded::Block::new_from_header_and_body(&header.view(), &body.view()))
match (self.block_header_data(hash), self.block_body(hash)) {
(Some(header), Some(body)) => {
let mut block = RlpStream::new_list(3);
let body_rlp = body.rlp();
block.append_raw(header.rlp().as_raw(), 1);
block.append_raw(body_rlp.at(0).as_raw(), 1);
block.append_raw(body_rlp.at(1).as_raw(), 1);
Some(encoded::Block::new(block.out()))
},
_ => None,
}
}
/// Get block header data
@@ -246,28 +259,36 @@ impl BlockProvider for BlockChain {
{
let read = self.block_headers.read();
if let Some(v) = read.get(hash) {
return Some(v.clone());
return Some(encoded::Header::new(v.clone()));
}
}
// Check if it's the best block
{
let best_block = self.best_block.read();
if &best_block.header.hash() == hash {
return Some(best_block.header.encoded())
if &best_block.hash == hash {
return Some(encoded::Header::new(
Rlp::new(&best_block.block).at(0).as_raw().to_vec()
))
}
}
// Read from DB and populate cache
let b = self.db.get(db::COL_HEADERS, hash)
.expect("Low level database error. Some issue with disk?")?;
let opt = self.db.get(db::COL_HEADERS, hash)
.expect("Low level database error. Some issue with disk?");
let header = encoded::Header::new(decompress(&b, blocks_swapper()).into_vec());
let mut write = self.block_headers.write();
write.insert(*hash, header.clone());
let result = match opt {
Some(b) => {
let bytes = decompress(&b, blocks_swapper()).into_vec();
let mut write = self.block_headers.write();
write.insert(*hash, bytes.clone());
Some(encoded::Header::new(bytes))
},
None => None
};
self.cache_man.lock().note_used(CacheId::BlockHeader(*hash));
Some(header)
result
}
/// Get block body data
@@ -276,56 +297,63 @@ impl BlockProvider for BlockChain {
{
let read = self.block_bodies.read();
if let Some(v) = read.get(hash) {
return Some(v.clone());
return Some(encoded::Body::new(v.clone()));
}
}
// Check if it's the best block
{
let best_block = self.best_block.read();
if &best_block.header.hash() == hash {
return Some(encoded::Body::new(Self::block_to_body(best_block.block.rlp().as_raw())));
if &best_block.hash == hash {
return Some(encoded::Body::new(Self::block_to_body(&best_block.block)));
}
}
// Read from DB and populate cache
let b = self.db.get(db::COL_BODIES, hash)
.expect("Low level database error. Some issue with disk?")?;
let opt = self.db.get(db::COL_BODIES, hash)
.expect("Low level database error. Some issue with disk?");
let body = encoded::Body::new(decompress(&b, blocks_swapper()).into_vec());
let mut write = self.block_bodies.write();
write.insert(*hash, body.clone());
let result = match opt {
Some(b) => {
let bytes = decompress(&b, blocks_swapper()).into_vec();
let mut write = self.block_bodies.write();
write.insert(*hash, bytes.clone());
Some(encoded::Body::new(bytes))
},
None => None
};
self.cache_man.lock().note_used(CacheId::BlockBody(*hash));
Some(body)
result
}
/// Get the familial details concerning a block.
fn block_details(&self, hash: &H256) -> Option<BlockDetails> {
let result = self.db.read_with_cache(db::COL_EXTRA, &self.block_details, hash)?;
let result = self.db.read_with_cache(db::COL_EXTRA, &self.block_details, hash);
self.cache_man.lock().note_used(CacheId::BlockDetails(*hash));
Some(result)
result
}
/// Get the hash of given block's number.
fn block_hash(&self, index: BlockNumber) -> Option<H256> {
let result = self.db.read_with_cache(db::COL_EXTRA, &self.block_hashes, &index)?;
let result = self.db.read_with_cache(db::COL_EXTRA, &self.block_hashes, &index);
self.cache_man.lock().note_used(CacheId::BlockHashes(index));
Some(result)
result
}
/// Get the address of transaction with given hash.
fn transaction_address(&self, hash: &H256) -> Option<TransactionAddress> {
let result = self.db.read_with_cache(db::COL_EXTRA, &self.transaction_addresses, hash)?;
let result = self.db.read_with_cache(db::COL_EXTRA, &self.transaction_addresses, hash);
self.cache_man.lock().note_used(CacheId::TransactionAddresses(*hash));
Some(result)
result
}
/// Get receipts of block with given hash.
fn block_receipts(&self, hash: &H256) -> Option<BlockReceipts> {
let result = self.db.read_with_cache(db::COL_EXTRA, &self.block_receipts, hash)?;
let result = self.db.read_with_cache(db::COL_EXTRA, &self.block_receipts, hash);
self.cache_man.lock().note_used(CacheId::BlockReceipts(*hash));
Some(result)
result
}
/// Returns numbers of blocks containing given bloom.
@@ -429,31 +457,33 @@ impl<'a> Iterator for EpochTransitionIter<'a> {
fn next(&mut self) -> Option<Self::Item> {
loop {
// some epochs never occurred on the main chain.
let (key, val) = self.prefix_iter.next()?;
match self.prefix_iter.next() {
Some((key, val)) => {
// iterator may continue beyond values beginning with this
// prefix.
if !key.starts_with(&EPOCH_KEY_PREFIX[..]) { return None }
// iterator may continue beyond values beginning with this
// prefix.
if !key.starts_with(&EPOCH_KEY_PREFIX[..]) {
return None
}
let transitions: EpochTransitions = ::rlp::decode(&val[..]);
let transitions: EpochTransitions = ::rlp::decode(&val[..]).expect("decode error: the db is corrupted or the data structure has changed");
// if there are multiple candidates, at most one will be on the
// canon chain.
for transition in transitions.candidates.into_iter() {
let is_in_canon_chain = self.chain.block_hash(transition.block_number)
.map_or(false, |hash| hash == transition.block_hash);
// if there are multiple candidates, at most one will be on the
// canon chain.
for transition in transitions.candidates.into_iter() {
let is_in_canon_chain = self.chain.block_hash(transition.block_number)
.map_or(false, |hash| hash == transition.block_hash);
// if the transition is within the block gap, there will only be
// one candidate, and it will be from a snapshot restored from.
let is_ancient = self.chain.first_block_number()
.map_or(false, |first| first > transition.block_number);
// if the transition is within the block gap, there will only be
// one candidate, and it will be from a snapshot restored from.
let is_ancient = self.chain.first_block_number()
.map_or(false, |first| first > transition.block_number);
if is_ancient || is_in_canon_chain {
return Some((transitions.number, transition))
}
}
if is_ancient || is_in_canon_chain {
return Some((transitions.number, transition))
// some epochs never occurred on the main chain.
}
None => return None,
}
}
}
@@ -462,7 +492,7 @@ impl<'a> Iterator for EpochTransitionIter<'a> {
impl BlockChain {
/// Create new instance of blockchain from given Genesis.
pub fn new(config: Config, genesis: &[u8], db: Arc<KeyValueDB>) -> BlockChain {
// 400 is the average size of the key
// 400 is the avarage size of the key
let cache_man = CacheManager::new(config.pref_cache_size, config.max_cache_size, 400);
let mut bc = BlockChain {
@@ -471,12 +501,7 @@ impl BlockChain {
elements_per_index: LOG_BLOOMS_ELEMENTS_PER_INDEX,
},
first_block: None,
best_block: RwLock::new(BestBlock {
// BestBlock will be overwritten anyway.
header: Default::default(),
total_difficulty: Default::default(),
block: encoded::Block::new(genesis.into()),
}),
best_block: RwLock::new(BestBlock::default()),
best_ancient_block: RwLock::new(None),
block_headers: RwLock::new(HashMap::new()),
block_bodies: RwLock::new(HashMap::new()),
@@ -501,7 +526,7 @@ impl BlockChain {
None => {
// best block does not exist
// we need to insert genesis into the cache
let block = view!(BlockView, genesis);
let block = BlockView::new(genesis);
let header = block.header_view();
let hash = block.hash();
@@ -527,21 +552,11 @@ impl BlockChain {
{
// Fetch best block details
let best_block_number = bc.block_number(&best_block_hash).unwrap();
let best_block_total_difficulty = bc.block_details(&best_block_hash).unwrap().total_difficulty;
let best_block_rlp = bc.block(&best_block_hash).unwrap();
let best_block_rlp = bc.block(&best_block_hash).unwrap().into_inner();
let best_block_timestamp = BlockView::new(&best_block_rlp).header().timestamp();
// and write them
let mut best_block = bc.best_block.write();
*best_block = BestBlock {
total_difficulty: best_block_total_difficulty,
header: best_block_rlp.decode_header(),
block: best_block_rlp,
};
}
{
let best_block_number = bc.best_block.read().header.number();
// Fetch first and best ancient block details
let raw_first = bc.db.get(db::COL_EXTRA, b"first").unwrap().map(|v| v.into_vec());
let mut best_ancient = bc.db.get(db::COL_EXTRA, b"ancient").unwrap().map(|h| H256::from_slice(&h));
let best_ancient_number;
@@ -584,6 +599,15 @@ impl BlockChain {
}
// and write them
let mut best_block = bc.best_block.write();
*best_block = BestBlock {
number: best_block_number,
total_difficulty: best_block_total_difficulty,
hash: best_block_hash,
timestamp: best_block_timestamp,
block: best_block_rlp,
};
if let (Some(hash), Some(number)) = (best_ancient, best_ancient_number) {
let mut best_ancient_block = bc.best_ancient_block.write();
*best_ancient_block = Some(BestAncientBlock {
@@ -703,7 +727,7 @@ impl BlockChain {
/// Supply a dummy parent total difficulty when the parent block may not be in the chain.
/// Returns true if the block is disconnected.
pub fn insert_unordered_block(&self, batch: &mut DBTransaction, bytes: &[u8], receipts: Vec<Receipt>, parent_td: Option<U256>, is_best: bool, is_ancient: bool) -> bool {
let block = view!(BlockView, bytes);
let block = BlockView::new(bytes);
let header = block.header_view();
let hash = header.hash();
@@ -738,6 +762,7 @@ impl BlockChain {
blocks_blooms: self.prepare_block_blooms_update(bytes, &info),
transactions_addresses: self.prepare_transaction_addresses_update(bytes, &info),
info: info,
timestamp: header.timestamp(),
block: bytes
}, is_best);
@@ -786,6 +811,7 @@ impl BlockChain {
blocks_blooms: self.prepare_block_blooms_update(bytes, &info),
transactions_addresses: self.prepare_transaction_addresses_update(bytes, &info),
info: info,
timestamp: header.timestamp(),
block: bytes,
}, is_best);
true
@@ -889,6 +915,7 @@ impl BlockChain {
let mut update = HashMap::new();
update.insert(block_hash, parent_details);
let mut write_details = self.block_details.write();
batch.extend_with_cache(db::COL_EXTRA, &mut *write_details, update, CacheUpdatePolicy::Overwrite);
@@ -900,7 +927,7 @@ impl BlockChain {
/// If the block is already known, does nothing.
pub fn insert_block(&self, batch: &mut DBTransaction, bytes: &[u8], receipts: Vec<Receipt>) -> ImportRoute {
// create views onto rlp
let block = view!(BlockView, bytes);
let block = BlockView::new(bytes);
let header = block.header_view();
let hash = header.hash();
@@ -935,6 +962,7 @@ impl BlockChain {
blocks_blooms: self.prepare_block_blooms_update(bytes, &info),
transactions_addresses: self.prepare_transaction_addresses_update(bytes, &info),
info: info.clone(),
timestamp: header.timestamp(),
block: bytes,
}, true);
@@ -1026,11 +1054,12 @@ impl BlockChain {
let mut best_block = self.pending_best_block.write();
if is_best && update.info.location != BlockLocation::Branch {
batch.put(db::COL_EXTRA, b"best", &update.info.hash);
let block = encoded::Block::new(update.block.to_vec());
*best_block = Some(BestBlock {
hash: update.info.hash,
number: update.info.number,
total_difficulty: update.info.total_difficulty,
header: block.decode_header(),
block,
timestamp: update.timestamp,
block: update.block.to_vec(),
});
}
@@ -1102,19 +1131,19 @@ impl BlockChain {
}
/// Given a block's `parent`, find every block header which represents a valid possible uncle.
pub fn find_uncle_headers(&self, parent: &H256, uncle_generations: usize) -> Option<Vec<encoded::Header>> {
self.find_uncle_hashes(parent, uncle_generations)
.map(|v| v.into_iter().filter_map(|h| self.block_header_data(&h)).collect())
pub fn find_uncle_headers(&self, parent: &H256, uncle_generations: usize) -> Option<Vec<Header>> {
self.find_uncle_hashes(parent, uncle_generations).map(|v| v.into_iter().filter_map(|h| self.block_header(&h)).collect())
}
/// Given a block's `parent`, find every block hash which represents a valid possible uncle.
pub fn find_uncle_hashes(&self, parent: &H256, uncle_generations: usize) -> Option<Vec<H256>> {
if !self.is_known(parent) {
return None;
}
if !self.is_known(parent) { return None; }
let mut excluded = HashSet::new();
let ancestry = self.ancestry_iter(parent.clone())?;
let ancestry = match self.ancestry_iter(parent.clone()) {
Some(iter) => iter,
None => return None,
};
for a in ancestry.clone().take(uncle_generations) {
if let Some(uncles) = self.uncle_hashes(&a) {
@@ -1140,7 +1169,7 @@ impl BlockChain {
/// This function returns modified block hashes.
fn prepare_block_hashes_update(&self, block_bytes: &[u8], info: &BlockInfo) -> HashMap<BlockNumber, H256> {
let mut block_hashes = HashMap::new();
let block = view!(BlockView, block_bytes);
let block = BlockView::new(block_bytes);
let header = block.header_view();
let number = header.number();
@@ -1167,7 +1196,7 @@ impl BlockChain {
/// This function returns modified block details.
/// Uses the given parent details or attempts to load them from the database.
fn prepare_block_details_update(&self, block_bytes: &[u8], info: &BlockInfo) -> HashMap<H256, BlockDetails> {
let block = view!(BlockView, block_bytes);
let block = BlockView::new(block_bytes);
let header = block.header_view();
let parent_hash = header.parent_hash();
@@ -1199,7 +1228,7 @@ impl BlockChain {
/// This function returns modified transaction addresses.
fn prepare_transaction_addresses_update(&self, block_bytes: &[u8], info: &BlockInfo) -> HashMap<H256, Option<TransactionAddress>> {
let block = view!(BlockView, block_bytes);
let block = BlockView::new(block_bytes);
let transaction_hashes = block.transaction_hashes();
match info.location {
@@ -1267,7 +1296,7 @@ impl BlockChain {
/// to bloom location in database (BlocksBloomLocation).
///
fn prepare_block_blooms_update(&self, block_bytes: &[u8], info: &BlockInfo) -> HashMap<GroupPosition, BloomGroup> {
let block = view!(BlockView, block_bytes);
let block = BlockView::new(block_bytes);
let header = block.header_view();
let log_blooms = match info.location {
@@ -1305,17 +1334,17 @@ impl BlockChain {
/// Get best block hash.
pub fn best_block_hash(&self) -> H256 {
self.best_block.read().header.hash()
self.best_block.read().hash
}
/// Get best block number.
pub fn best_block_number(&self) -> BlockNumber {
self.best_block.read().header.number()
self.best_block.read().number
}
/// Get best block timestamp.
pub fn best_block_timestamp(&self) -> u64 {
self.best_block.read().header.timestamp()
self.best_block.read().timestamp
}
/// Get best block total difficulty.
@@ -1324,8 +1353,10 @@ impl BlockChain {
}
/// Get best block header
pub fn best_block_header(&self) -> Header {
self.best_block.read().header.clone()
pub fn best_block_header(&self) -> encoded::Header {
let block = self.best_block.read();
let raw = BlockView::new(&block.block).header_view().rlp().as_raw().to_vec();
encoded::Header::new(raw)
}
/// Get current cache size.
@@ -1386,32 +1417,26 @@ impl BlockChain {
/// Create a block body from a block.
pub fn block_to_body(block: &[u8]) -> Bytes {
let mut body = RlpStream::new_list(2);
let block_view = view!(BlockView, block);
body.append_raw(block_view.transactions_rlp().as_raw(), 1);
body.append_raw(block_view.uncles_rlp().as_raw(), 1);
let block_rlp = Rlp::new(block);
body.append_raw(block_rlp.at(1).as_raw(), 1);
body.append_raw(block_rlp.at(2).as_raw(), 1);
body.out()
}
/// Returns general blockchain information
pub fn chain_info(&self) -> BlockChainInfo {
// Make sure to call internal methods first to avoid
// recursive locking of `best_block`.
let first_block_hash = self.first_block();
let first_block_number = self.first_block_number().into();
let genesis_hash = self.genesis_hash();
// ensure data consistencly by locking everything first
let best_block = self.best_block.read();
let best_ancient_block = self.best_ancient_block.read();
BlockChainInfo {
total_difficulty: best_block.total_difficulty,
pending_total_difficulty: best_block.total_difficulty,
genesis_hash,
best_block_hash: best_block.header.hash(),
best_block_number: best_block.header.number(),
best_block_timestamp: best_block.header.timestamp(),
first_block_hash,
first_block_number,
total_difficulty: best_block.total_difficulty.clone(),
pending_total_difficulty: best_block.total_difficulty.clone(),
genesis_hash: self.genesis_hash(),
best_block_hash: best_block.hash,
best_block_number: best_block.number,
best_block_timestamp: best_block.timestamp,
first_block_hash: self.first_block(),
first_block_number: From::from(self.first_block_number()),
ancient_block_hash: best_ancient_block.as_ref().map(|b| b.hash),
ancient_block_number: best_ancient_block.as_ref().map(|b| b.number),
}
@@ -1429,10 +1454,7 @@ mod tests {
use ethereum_types::*;
use receipt::{Receipt, TransactionOutcome};
use blockchain::{BlockProvider, BlockChain, Config, ImportRoute};
use test_helpers::{
generate_dummy_blockchain, generate_dummy_blockchain_with_extra,
generate_dummy_empty_blockchain
};
use tests::helpers::*;
use blockchain::generator::{BlockGenerator, BlockBuilder, BlockOptions};
use blockchain::extras::TransactionAddress;
use transaction::{Transaction, Action};
@@ -1541,11 +1563,7 @@ mod tests {
let b4b = b3a.add_block_with_difficulty(9);
let b5b = b4a.add_block_with_difficulty(9);
let uncle_headers = vec![
b4b.last().header().encoded(),
b3b.last().header().encoded(),
b2b.last().header().encoded(),
];
let uncle_headers = vec![b4b.last().header(), b3b.last().header(), b2b.last().header()];
let b4a_hash = b4a.last().hash();
let generator = BlockGenerator::new(
@@ -1868,10 +1886,10 @@ mod tests {
assert_eq!(bc.best_block_number(), 2999);
let best_hash = bc.best_block_hash();
let mut block_header = bc.block_header_data(&best_hash);
let mut block_header = bc.block_header(&best_hash);
while !block_header.is_none() {
block_header = bc.block_header_data(&block_header.unwrap().parent_hash());
block_header = bc.block_header(block_header.unwrap().parent_hash());
}
assert!(bc.cache_size().blocks > 1024 * 1024);

View File

@@ -41,7 +41,7 @@ impl Block {
#[inline]
pub fn hash(&self) -> H256 {
view!(BlockView, &self.encoded()).header_view().hash()
BlockView::new(&self.encoded()).header_view().hash()
}
#[inline]

View File

@@ -20,7 +20,7 @@ use ethereum_types::H256;
use blockchain::block_info::{BlockInfo, BlockLocation};
/// Import route for newly inserted block.
#[derive(Debug, PartialEq, Clone)]
#[derive(Debug, PartialEq)]
pub struct ImportRoute {
/// Blocks that were invalidated by new block.
pub retracted: Vec<H256>,

View File

@@ -9,6 +9,8 @@ use blooms::{BloomGroup, GroupPosition};
pub struct ExtrasUpdate<'a> {
/// Block info.
pub info: BlockInfo,
/// Block timestamp.
pub timestamp: u64,
/// Current block uncompressed rlp bytes
pub block: &'a [u8],
/// Modified block hashes.

View File

@@ -32,16 +32,16 @@ const HEAVY_VERIFY_RATE: f32 = 0.02;
/// Ancient block verifier: import an ancient sequence of blocks in order from a starting
/// epoch.
pub struct AncientVerifier {
cur_verifier: RwLock<Option<Box<EpochVerifier<EthereumMachine>>>>,
cur_verifier: RwLock<Box<EpochVerifier<EthereumMachine>>>,
engine: Arc<EthEngine>,
}
impl AncientVerifier {
/// Create a new ancient block verifier with the given engine.
pub fn new(engine: Arc<EthEngine>) -> Self {
/// Create a new ancient block verifier with the given engine and initial verifier.
pub fn new(engine: Arc<EthEngine>, start_verifier: Box<EpochVerifier<EthereumMachine>>) -> Self {
AncientVerifier {
cur_verifier: RwLock::new(None),
engine,
cur_verifier: RwLock::new(start_verifier),
engine: engine,
}
}
@@ -53,49 +53,17 @@ impl AncientVerifier {
header: &Header,
chain: &BlockChain,
) -> Result<(), ::error::Error> {
// perform verification
let verified = if let Some(ref cur_verifier) = *self.cur_verifier.read() {
match rng.gen::<f32>() <= HEAVY_VERIFY_RATE {
true => cur_verifier.verify_heavy(header)?,
false => cur_verifier.verify_light(header)?,
}
true
} else {
false
};
// when there is no verifier initialize it.
// We use a bool flag to avoid double locking in the happy case
if !verified {
{
let mut cur_verifier = self.cur_verifier.write();
if cur_verifier.is_none() {
*cur_verifier = Some(self.initial_verifier(header, chain)?);
}
}
// Call again to verify.
return self.verify(rng, header, chain);
match rng.gen::<f32>() <= HEAVY_VERIFY_RATE {
true => self.cur_verifier.read().verify_heavy(header)?,
false => self.cur_verifier.read().verify_light(header)?,
}
// ancient import will only use transitions obtained from the snapshot.
if let Some(transition) = chain.epoch_transition(header.number(), header.hash()) {
let v = self.engine.epoch_verifier(&header, &transition.proof).known_confirmed()?;
*self.cur_verifier.write() = Some(v);
*self.cur_verifier.write() = v;
}
Ok(())
}
fn initial_verifier(&self, header: &Header, chain: &BlockChain)
-> Result<Box<EpochVerifier<EthereumMachine>>, ::error::Error>
{
trace!(target: "client", "Initializing ancient block restoration.");
let current_epoch_data = chain.epoch_transitions()
.take_while(|&(_, ref t)| t.block_number < header.number())
.last()
.map(|(_, t)| t.proof)
.expect("At least one epoch entry (genesis) always stored; qed");
self.engine.epoch_verifier(&header, &current_epoch_data).known_confirmed()
}
}

View File

@@ -14,105 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use bytes::Bytes;
use ethereum_types::H256;
use transaction::UnverifiedTransaction;
use blockchain::ImportRoute;
use std::time::Duration;
use std::collections::HashMap;
/// Messages to broadcast via chain
pub enum ChainMessageType {
/// Consensus message
Consensus(Vec<u8>),
/// Message with private transaction
PrivateTransaction(Vec<u8>),
/// Message with signed private transaction
SignedPrivateTransaction(Vec<u8>),
}
/// Route type to indicate whether it is enacted or retracted.
#[derive(Clone)]
pub enum ChainRouteType {
/// Enacted block
Enacted,
/// Retracted block
Retracted
}
/// A complete chain enacted retracted route.
#[derive(Default, Clone)]
pub struct ChainRoute {
route: Vec<(H256, ChainRouteType)>,
enacted: Vec<H256>,
retracted: Vec<H256>,
}
impl<'a> From<&'a [ImportRoute]> for ChainRoute {
fn from(import_results: &'a [ImportRoute]) -> ChainRoute {
ChainRoute::new(import_results.iter().flat_map(|route| {
route.retracted.iter().map(|h| (*h, ChainRouteType::Retracted))
.chain(route.enacted.iter().map(|h| (*h, ChainRouteType::Enacted)))
}).collect())
}
}
impl ChainRoute {
/// Create a new ChainRoute based on block hash and route type pairs.
pub fn new(route: Vec<(H256, ChainRouteType)>) -> Self {
let (enacted, retracted) = Self::to_enacted_retracted(&route);
Self { route, enacted, retracted }
}
/// Gather all non-duplicate enacted and retracted blocks.
fn to_enacted_retracted(route: &[(H256, ChainRouteType)]) -> (Vec<H256>, Vec<H256>) {
fn map_to_vec(map: Vec<(H256, bool)>) -> Vec<H256> {
map.into_iter().map(|(k, _v)| k).collect()
}
// Because we are doing multiple inserts some of the blocks that were enacted in import `k`
// could be retracted in import `k+1`. This is why to understand if after all inserts
// the block is enacted or retracted we iterate over all routes and at the end final state
// will be in the hashmap
let map = route.iter().fold(HashMap::new(), |mut map, route| {
match &route.1 {
&ChainRouteType::Enacted => {
map.insert(route.0, true);
},
&ChainRouteType::Retracted => {
map.insert(route.0, false);
},
}
map
});
// Split to enacted retracted (using hashmap value)
let (enacted, retracted) = map.into_iter().partition(|&(_k, v)| v);
// And convert tuples to keys
(map_to_vec(enacted), map_to_vec(retracted))
}
/// Consume route and return the enacted retracted form.
pub fn into_enacted_retracted(self) -> (Vec<H256>, Vec<H256>) {
(self.enacted, self.retracted)
}
/// All non-duplicate enacted blocks.
pub fn enacted(&self) -> &[H256] {
&self.enacted
}
/// All non-duplicate retracted blocks.
pub fn retracted(&self) -> &[H256] {
&self.retracted
}
/// All blocks in the route.
pub fn route(&self) -> &[(H256, ChainRouteType)] {
&self.route
}
}
use bytes::Bytes;
/// Represents what has to be handled by actor listening to chain events
pub trait ChainNotify : Send + Sync {
@@ -121,11 +24,12 @@ pub trait ChainNotify : Send + Sync {
&self,
_imported: Vec<H256>,
_invalid: Vec<H256>,
_route: ChainRoute,
_enacted: Vec<H256>,
_retracted: Vec<H256>,
_sealed: Vec<H256>,
// Block bytes.
_proposed: Vec<Bytes>,
_duration: Duration,
_duration: u64,
) {
// does nothing by default
}
@@ -141,11 +45,11 @@ pub trait ChainNotify : Send + Sync {
}
/// fires when chain broadcasts a message
fn broadcast(&self, _message_type: ChainMessageType) {}
fn broadcast(&self, _data: Vec<u8>) {}
/// fires when new transactions are received from a peer
fn transactions_received(&self,
_txs: &[UnverifiedTransaction],
_hashes: Vec<H256>,
_peer_id: usize,
) {
// does nothing by default

File diff suppressed because it is too large Load Diff

View File

@@ -15,11 +15,13 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::str::FromStr;
use std::path::Path;
use std::fmt::{Display, Formatter, Error as FmtError};
use mode::Mode as IpcMode;
use verification::{VerifierType, QueueConfig};
use journaldb;
use kvdb_rocksdb::CompactionProfile;
pub use std::time::Duration;
pub use blockchain::Config as BlockChainConfig;
@@ -43,6 +45,17 @@ impl Default for DatabaseCompactionProfile {
}
}
impl DatabaseCompactionProfile {
/// Returns corresponding compaction profile.
pub fn compaction_profile(&self, db_path: &Path) -> CompactionProfile {
match *self {
DatabaseCompactionProfile::Auto => CompactionProfile::auto(db_path),
DatabaseCompactionProfile::SSD => CompactionProfile::ssd(),
DatabaseCompactionProfile::HDD => CompactionProfile::hdd(),
}
}
}
impl FromStr for DatabaseCompactionProfile {
type Err = String;
@@ -61,16 +74,22 @@ impl FromStr for DatabaseCompactionProfile {
pub enum Mode {
/// Always on.
Active,
/// Goes offline after client is inactive for some (given) time, but
/// Goes offline after RLP is inactive for some (given) time, but
/// comes back online after a while of inactivity.
Passive(Duration, Duration),
/// Goes offline after client is inactive for some (given) time and
/// Goes offline after RLP is inactive for some (given) time and
/// stays inactive.
Dark(Duration),
/// Always off.
Off,
}
impl Default for Mode {
fn default() -> Self {
Mode::Active
}
}
impl Display for Mode {
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
match *self {
@@ -106,7 +125,7 @@ impl From<IpcMode> for Mode {
/// Client configuration. Includes configs for all sub-systems.
#[derive(Debug, PartialEq, Clone)]
#[derive(Debug, PartialEq, Default)]
pub struct ClientConfig {
/// Block queue configuration.
pub queue: QueueConfig,
@@ -144,39 +163,11 @@ pub struct ClientConfig {
pub history_mem: usize,
/// Check seal valididity on block import
pub check_seal: bool,
/// Maximal number of transactions queued for verification in a separate thread.
pub transaction_verification_queue_size: usize,
}
impl Default for ClientConfig {
fn default() -> Self {
let mb = 1024 * 1024;
ClientConfig {
queue: Default::default(),
blockchain: Default::default(),
tracing: Default::default(),
vm_type: Default::default(),
fat_db: false,
pruning: journaldb::Algorithm::OverlayRecent,
name: "default".into(),
db_cache_size: None,
db_compaction: Default::default(),
db_wal: true,
mode: Mode::Active,
spec_name: "".into(),
verifier_type: VerifierType::Canon,
state_cache_size: 1 * mb,
jump_table_size: 1 * mb,
history: 64,
history_mem: 32 * mb,
check_seal: true,
transaction_verification_queue_size: 8192,
}
}
}
#[cfg(test)]
mod test {
use super::{DatabaseCompactionProfile};
use super::{DatabaseCompactionProfile, Mode};
#[test]
fn test_default_compaction_profile() {
@@ -189,4 +180,9 @@ mod test {
assert_eq!(DatabaseCompactionProfile::SSD, "ssd".parse().unwrap());
assert_eq!(DatabaseCompactionProfile::HDD, "hdd".parse().unwrap());
}
#[test]
fn test_mode_default() {
assert_eq!(Mode::default(), Mode::Active);
}
}

View File

@@ -18,10 +18,10 @@
use std::fmt;
use std::sync::Arc;
use ethereum_types::{H256, U256, H160};
use ethereum_types::{H256, U256};
use {factory, journaldb, trie, kvdb_memorydb, bytes};
use kvdb::{self, KeyValueDB};
use {state, state_db, client, executive, trace, transaction, db, spec, pod_state, log_entry, receipt};
use {state, state_db, client, executive, trace, transaction, db, spec, pod_state};
use factory::Factories;
use evm::{VMType, FinalizationResult};
use vm::{self, ActionParams};
@@ -79,15 +79,6 @@ pub struct EvmTestClient<'a> {
spec: &'a spec::Spec,
}
impl<'a> fmt::Debug for EvmTestClient<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("EvmTestClient")
.field("state", &self.state)
.field("spec", &self.spec.name)
.finish()
}
}
impl<'a> EvmTestClient<'a> {
/// Converts a json spec definition into spec.
pub fn spec_from_json(spec: &ForkSpec) -> Option<&'static spec::Spec> {
@@ -169,19 +160,10 @@ impl<'a> EvmTestClient<'a> {
Ok(state)
}
/// Return current state.
pub fn state(&self) -> &state::State<state_db::StateDB> {
&self.state
}
/// Execute the VM given ActionParams and tracer.
/// Returns amount of gas left and the output.
pub fn call<T: trace::Tracer, V: trace::VMTracer>(
&mut self,
params: ActionParams,
tracer: &mut T,
vm_tracer: &mut V,
) -> Result<FinalizationResult, EvmTestError>
pub fn call<T: trace::VMTracer>(&mut self, params: ActionParams, vm_tracer: &mut T)
-> Result<FinalizationResult, EvmTestError>
{
let genesis = self.spec.genesis_header();
let info = client::EnvInfo {
@@ -194,26 +176,26 @@ impl<'a> EvmTestClient<'a> {
gas_limit: *genesis.gas_limit(),
};
let mut substate = state::Substate::new();
let mut tracer = trace::NoopTracer;
let mut output = vec![];
let mut executive = executive::Executive::new(&mut self.state, &info, self.spec.engine.machine());
executive.call(
params,
&mut substate,
bytes::BytesRef::Flexible(&mut output),
tracer,
&mut tracer,
vm_tracer,
).map_err(EvmTestError::Evm)
}
/// Executes a SignedTransaction within context of the provided state and `EnvInfo`.
/// Returns the state root, gas left and the output.
pub fn transact<T: trace::Tracer, V: trace::VMTracer>(
pub fn transact<T: trace::VMTracer>(
&mut self,
env_info: &client::EnvInfo,
transaction: transaction::SignedTransaction,
tracer: T,
vm_tracer: V,
) -> TransactResult<T::Output, V::Output> {
vm_tracer: T,
) -> TransactResult<T::Output> {
let initial_gas = transaction.gas;
// Verify transaction
let is_ok = transaction.verify_basic(true, None, env_info.number >= self.spec.engine.params().eip86_transition);
@@ -225,8 +207,8 @@ impl<'a> EvmTestClient<'a> {
}
// Apply transaction
let tracer = trace::NoopTracer;
let result = self.state.apply_with_tracing(&env_info, self.spec.engine.machine(), &transaction, tracer, vm_tracer);
let scheme = self.spec.engine.machine().create_address_scheme(env_info.number);
match result {
Ok(result) => {
@@ -234,16 +216,8 @@ impl<'a> EvmTestClient<'a> {
TransactResult::Ok {
state_root: *self.state.root(),
gas_left: initial_gas - result.receipt.gas_used,
outcome: result.receipt.outcome,
output: result.output,
trace: result.trace,
vm_trace: result.vm_trace,
logs: result.receipt.logs,
contract_address: if let transaction::Action::Create = transaction.action {
Some(executive::contract_address(scheme, &transaction.sender(), &transaction.nonce, &transaction.data).0)
} else {
None
}
}
},
Err(error) => TransactResult::Err {
@@ -255,8 +229,7 @@ impl<'a> EvmTestClient<'a> {
}
/// A result of applying transaction to the state.
#[derive(Debug)]
pub enum TransactResult<T, V> {
pub enum TransactResult<T> {
/// Successful execution
Ok {
/// State root
@@ -265,16 +238,8 @@ pub enum TransactResult<T, V> {
gas_left: U256,
/// Output
output: Vec<u8>,
/// Traces
trace: Vec<T>,
/// VM Traces
vm_trace: Option<V>,
/// Created contract address (if any)
contract_address: Option<H160>,
/// Generated logs
logs: Vec<log_entry::LogEntry>,
/// outcome
outcome: receipt::TransactionOutcome,
vm_trace: Option<T>,
},
/// Transaction failed to run
Err {

View File

@@ -1,57 +0,0 @@
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::fmt;
use bytes::Bytes;
use client::Client;
use ethereum_types::H256;
use snapshot::ManifestData;
/// Message type for external and internal events
#[derive(Debug)]
pub enum ClientIoMessage {
/// Best Block Hash in chain has been changed
NewChainHead,
/// A block is ready
BlockVerified,
/// Begin snapshot restoration
BeginRestoration(ManifestData),
/// Feed a state chunk to the snapshot service
FeedStateChunk(H256, Bytes),
/// Feed a block chunk to the snapshot service
FeedBlockChunk(H256, Bytes),
/// Take a snapshot for the block with given number.
TakeSnapshot(u64),
/// Execute wrapped closure
Execute(Callback),
}
impl ClientIoMessage {
/// Create new `ClientIoMessage` that executes given procedure.
pub fn execute<F: Fn(&Client) + Send + Sync + 'static>(fun: F) -> Self {
ClientIoMessage::Execute(Callback(Box::new(fun)))
}
}
/// A function to invoke in the client thread.
pub struct Callback(pub Box<Fn(&Client) + Send + Sync>);
impl fmt::Debug for Callback {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "<callback>")
}
}

View File

@@ -17,27 +17,22 @@
//! Blockchain database client.
mod ancient_import;
mod client;
mod config;
mod error;
mod evm_test_client;
mod io_message;
mod test_client;
mod trace;
mod client;
pub use self::client::*;
pub use self::config::{Mode, ClientConfig, DatabaseCompactionProfile, BlockChainConfig, VMType};
pub use self::error::Error;
pub use self::evm_test_client::{EvmTestClient, EvmTestError, TransactResult};
pub use self::io_message::ClientIoMessage;
pub use self::test_client::{TestBlockChainClient, EachBlockWith};
pub use self::chain_notify::{ChainNotify, ChainRoute, ChainRouteType, ChainMessageType};
pub use self::traits::{
Nonce, Balance, ChainInfo, BlockInfo, ReopenBlock, PrepareOpenBlock, CallContract, TransactionInfo, RegistryInfo, ScheduleInfo, ImportSealedBlock, BroadcastProposalBlock, ImportBlock,
StateOrBlock, StateClient, Call, EngineInfo, AccountData, BlockChain, BlockProducer, SealedBlockImporter
};
pub use state::StateInfo;
pub use self::traits::{BlockChainClient, EngineClient, ProvingBlockChainClient, IoClient};
pub use self::chain_notify::ChainNotify;
pub use self::traits::{BlockChainClient, MiningBlockChainClient, EngineClient};
pub use self::traits::ProvingBlockChainClient;
pub use types::ids::*;
pub use types::trace_filter::Filter as TraceFilter;
@@ -47,10 +42,9 @@ 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::{BlockImportError, TransactionImportError};
pub use verification::VerifierType;
mod traits;
mod chain_notify;
mod private_notify;

View File

@@ -1,23 +0,0 @@
// Copyright 2015-2017 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/>.
use error::TransactionImportError;
/// Represent private transactions handler inside the client
pub trait PrivateNotify : Send + Sync {
/// fires when private transaction message queued via client io queue
fn private_transaction_queued(&self) -> Result<(), TransactionImportError>;
}

View File

@@ -16,7 +16,7 @@
//! Test client.
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering as AtomicOrder};
use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrder};
use std::sync::Arc;
use std::collections::{HashMap, BTreeMap};
use std::mem;
@@ -27,26 +27,26 @@ use ethereum_types::{H256, U256, Address};
use parking_lot::RwLock;
use journaldb;
use kvdb::DBValue;
use kvdb_memorydb;
use kvdb_rocksdb::{Database, DatabaseConfig};
use bytes::Bytes;
use rlp::{Rlp, RlpStream};
use rlp::*;
use ethkey::{Generator, Random};
use ethcore_miner::pool::VerifiedTransaction;
use transaction::{self, Transaction, LocalizedTransaction, SignedTransaction, Action};
use tempdir::TempDir;
use transaction::{self, Transaction, LocalizedTransaction, PendingTransaction, SignedTransaction, Action};
use blockchain::{TreeRoute, BlockReceipts};
use client::{
Nonce, Balance, ChainInfo, BlockInfo, ReopenBlock, CallContract, TransactionInfo, RegistryInfo,
PrepareOpenBlock, BlockChainClient, BlockChainInfo, BlockStatus, BlockId,
BlockChainClient, MiningBlockChainClient, BlockChainInfo, BlockStatus, BlockId,
TransactionId, UncleId, TraceId, TraceFilter, LastHashes, CallAnalytics, BlockImportError,
ProvingBlockChainClient, ScheduleInfo, ImportSealedBlock, BroadcastProposalBlock, ImportBlock, StateOrBlock,
Call, StateClient, EngineInfo, AccountData, BlockChain, BlockProducer, SealedBlockImporter, IoClient
ProvingBlockChainClient,
};
use db::{NUM_COLUMNS, COL_STATE};
use header::{Header as BlockHeader, BlockNumber};
use filter::Filter;
use log_entry::LocalizedLogEntry;
use receipt::{Receipt, LocalizedReceipt, TransactionOutcome};
use error::ImportResult;
use error::{ImportResult, Error as EthcoreError};
use evm::VMType;
use factory::VmFactory;
use vm::Schedule;
use miner::{Miner, MinerService};
use spec::Spec;
@@ -60,12 +60,7 @@ use executive::Executed;
use error::CallError;
use trace::LocalizedTrace;
use state_db::StateDB;
use header::Header;
use encoded;
use engines::EthEngine;
use trie;
use state::StateInfo;
use views::BlockView;
/// Test client.
pub struct TestBlockChainClient {
@@ -101,6 +96,8 @@ pub struct TestBlockChainClient {
pub miner: Arc<Miner>,
/// Spec
pub spec: Spec,
/// VM Factory
pub vm_factory: VmFactory,
/// Timestamp assigned to latest sealed block
pub latest_block_timestamp: RwLock<u64>,
/// Ancient block info.
@@ -111,8 +108,6 @@ pub struct TestBlockChainClient {
pub traces: RwLock<Option<Vec<LocalizedTrace>>>,
/// Pruning history size to report.
pub history: RwLock<Option<u64>>,
/// Is disabled
pub disabled: AtomicBool,
}
/// Used for generating test client blocks.
@@ -171,14 +166,14 @@ impl TestBlockChainClient {
receipts: RwLock::new(HashMap::new()),
logs: RwLock::new(Vec::new()),
queue_size: AtomicUsize::new(0),
miner: Arc::new(Miner::new_for_tests(&spec, None)),
miner: Arc::new(Miner::with_spec(&spec)),
spec: spec,
vm_factory: VmFactory::new(VMType::Interpreter, 1024 * 1024),
latest_block_timestamp: RwLock::new(10_000_000),
ancient_block: RwLock::new(None),
first_block: RwLock::new(None),
traces: RwLock::new(None),
history: RwLock::new(None),
disabled: AtomicBool::new(false),
};
// insert genesis hash.
@@ -289,7 +284,7 @@ impl TestBlockChainClient {
/// Make a bad block by setting invalid extra data.
pub fn corrupt_block(&self, n: BlockNumber) {
let hash = self.block_hash(BlockId::Number(n)).unwrap();
let mut header: BlockHeader = self.block_header(BlockId::Number(n)).unwrap().decode().expect("decoding failed");
let mut header: BlockHeader = self.block_header(BlockId::Number(n)).unwrap().decode();
header.set_extra_data(b"This extra data is way too long to be considered valid".to_vec());
let mut rlp = RlpStream::new_list(3);
rlp.append(&header);
@@ -301,7 +296,7 @@ impl TestBlockChainClient {
/// Make a bad block by setting invalid parent hash.
pub fn corrupt_block_parent(&self, n: BlockNumber) {
let hash = self.block_hash(BlockId::Number(n)).unwrap();
let mut header: BlockHeader = self.block_header(BlockId::Number(n)).unwrap().decode().expect("decoding failed");
let mut header: BlockHeader = self.block_header(BlockId::Number(n)).unwrap().decode();
header.set_parent_hash(H256::from(42));
let mut rlp = RlpStream::new_list(3);
rlp.append(&header);
@@ -310,7 +305,7 @@ impl TestBlockChainClient {
self.blocks.write().insert(hash, rlp.out());
}
/// Get block hash with `delta` as offset from the most recent blocks.
/// TODO:
pub fn block_hash_delta_minus(&mut self, delta: usize) -> H256 {
let blocks_read = self.numbers.read();
let index = blocks_read.len() - delta;
@@ -322,7 +317,7 @@ impl TestBlockChainClient {
BlockId::Hash(hash) => Some(hash),
BlockId::Number(n) => self.numbers.read().get(&(n as usize)).cloned(),
BlockId::Earliest => self.numbers.read().get(&0).cloned(),
BlockId::Latest => self.numbers.read().get(&(self.numbers.read().len() - 1)).cloned()
BlockId::Latest | BlockId::Pending => self.numbers.read().get(&(self.numbers.read().len() - 1)).cloned()
}
}
@@ -341,8 +336,8 @@ impl TestBlockChainClient {
self.set_balance(signed_tx.sender(), 10_000_000_000_000_000_000u64.into());
let hash = signed_tx.hash();
let res = self.miner.import_external_transactions(self, vec![signed_tx.into()]);
let res = res.into_iter().next().unwrap();
assert!(res.is_ok());
let res = res.into_iter().next().unwrap().expect("Successful import");
assert_eq!(res, transaction::ImportResult::Current);
hash
}
@@ -355,30 +350,28 @@ impl TestBlockChainClient {
pub fn set_history(&self, h: Option<u64>) {
*self.history.write() = h;
}
/// Returns true if the client has been disabled.
pub fn is_disabled(&self) -> bool {
self.disabled.load(AtomicOrder::Relaxed)
}
}
pub fn get_temp_state_db() -> StateDB {
let db = kvdb_memorydb::create(NUM_COLUMNS.unwrap_or(0));
pub fn get_temp_state_db() -> (StateDB, TempDir) {
let tempdir = TempDir::new("").unwrap();
let db = Database::open(&DatabaseConfig::with_columns(NUM_COLUMNS), tempdir.path().to_str().unwrap()).unwrap();
let journal_db = journaldb::new(Arc::new(db), journaldb::Algorithm::EarlyMerge, COL_STATE);
StateDB::new(journal_db, 1024 * 1024)
let state_db = StateDB::new(journal_db, 1024 * 1024);
(state_db, tempdir)
}
impl ReopenBlock for TestBlockChainClient {
fn reopen_block(&self, block: ClosedBlock) -> OpenBlock {
block.reopen(&*self.spec.engine)
impl MiningBlockChainClient for TestBlockChainClient {
fn as_block_chain_client(&self) -> &BlockChainClient { self }
fn latest_schedule(&self) -> Schedule {
Schedule::new_post_eip150(24576, true, true, true)
}
}
impl PrepareOpenBlock for TestBlockChainClient {
fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes) -> OpenBlock {
let engine = &*self.spec.engine;
let genesis_header = self.spec.genesis_header();
let db = self.spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap();
let (state_db, _tempdir) = get_temp_state_db();
let db = self.spec.ensure_db_good(state_db, &Default::default()).unwrap();
let last_hashes = vec![genesis_header.hash()];
let mut open_block = OpenBlock::new(
@@ -393,220 +386,43 @@ impl PrepareOpenBlock for TestBlockChainClient {
extra_data,
false,
).expect("Opening block for tests will not fail.");
// TODO [todr] Override timestamp for predictability
// TODO [todr] Override timestamp for predictability (set_timestamp_now kind of sucks)
open_block.set_timestamp(*self.latest_block_timestamp.read());
open_block
}
}
impl ScheduleInfo for TestBlockChainClient {
fn latest_schedule(&self) -> Schedule {
Schedule::new_post_eip150(24576, true, true, true)
fn reopen_block(&self, block: ClosedBlock) -> OpenBlock {
block.reopen(&*self.spec.engine)
}
fn vm_factory(&self) -> &VmFactory {
&self.vm_factory
}
}
impl ImportSealedBlock for TestBlockChainClient {
fn import_sealed_block(&self, _block: SealedBlock) -> ImportResult {
Ok(H256::default())
}
}
impl BlockProducer for TestBlockChainClient {}
impl BroadcastProposalBlock for TestBlockChainClient {
fn broadcast_proposal_block(&self, _block: SealedBlock) {}
}
impl SealedBlockImporter for TestBlockChainClient {}
impl ::miner::TransactionVerifierClient for TestBlockChainClient {}
impl ::miner::BlockChainClient for TestBlockChainClient {}
impl Nonce for TestBlockChainClient {
fn nonce(&self, address: &Address, id: BlockId) -> Option<U256> {
match id {
BlockId::Latest => Some(self.nonces.read().get(address).cloned().unwrap_or(self.spec.params().account_start_nonce)),
_ => None,
}
}
fn latest_nonce(&self, address: &Address) -> U256 {
self.nonce(address, BlockId::Latest).unwrap()
}
}
impl Balance for TestBlockChainClient {
fn balance(&self, address: &Address, state: StateOrBlock) -> Option<U256> {
match state {
StateOrBlock::Block(BlockId::Latest) | StateOrBlock::State(_) => Some(self.balances.read().get(address).cloned().unwrap_or_else(U256::zero)),
_ => None,
}
}
fn latest_balance(&self, address: &Address) -> U256 {
self.balance(address, BlockId::Latest.into()).unwrap()
}
}
impl AccountData for TestBlockChainClient {}
impl ChainInfo for TestBlockChainClient {
fn chain_info(&self) -> BlockChainInfo {
let number = self.blocks.read().len() as BlockNumber - 1;
BlockChainInfo {
total_difficulty: *self.difficulty.read(),
pending_total_difficulty: *self.difficulty.read(),
genesis_hash: self.genesis_hash.clone(),
best_block_hash: self.last_hash.read().clone(),
best_block_number: number,
best_block_timestamp: number,
first_block_hash: self.first_block.read().as_ref().map(|x| x.0),
first_block_number: self.first_block.read().as_ref().map(|x| x.1),
ancient_block_hash: self.ancient_block.read().as_ref().map(|x| x.0),
ancient_block_number: self.ancient_block.read().as_ref().map(|x| x.1)
}
}
}
impl BlockInfo for TestBlockChainClient {
fn block_header(&self, id: BlockId) -> Option<encoded::Header> {
self.block_hash(id)
.and_then(|hash| self.blocks.read().get(&hash).map(|r| view!(BlockView, r).header_rlp().as_raw().to_vec()))
.map(encoded::Header::new)
}
fn best_block_header(&self) -> Header {
self.block_header(BlockId::Hash(self.chain_info().best_block_hash))
.expect("Best block always has header.")
.decode()
.expect("decoding failed")
}
fn block(&self, id: BlockId) -> Option<encoded::Block> {
self.block_hash(id)
.and_then(|hash| self.blocks.read().get(&hash).cloned())
.map(encoded::Block::new)
}
fn code_hash(&self, address: &Address, id: BlockId) -> Option<H256> {
match id {
BlockId::Latest => self.code.read().get(address).map(|c| keccak(&c)),
_ => None,
}
}
}
impl CallContract for TestBlockChainClient {
fn call_contract(&self, _id: BlockId, _address: Address, _data: Bytes) -> Result<Bytes, String> { Ok(vec![]) }
}
impl TransactionInfo for TestBlockChainClient {
fn transaction_block(&self, _id: TransactionId) -> Option<H256> {
None // Simple default.
}
}
impl BlockChain for TestBlockChainClient {}
impl RegistryInfo for TestBlockChainClient {
fn registry_address(&self, _name: String, _block: BlockId) -> Option<Address> { None }
}
impl ImportBlock for TestBlockChainClient {
fn import_block(&self, b: Bytes) -> Result<H256, BlockImportError> {
let header = view!(BlockView, &b).header();
let h = header.hash();
let number: usize = header.number() as usize;
if number > self.blocks.read().len() {
panic!("Unexpected block number. Expected {}, got {}", self.blocks.read().len(), number);
}
if number > 0 {
match self.blocks.read().get(header.parent_hash()) {
Some(parent) => {
let parent = view!(BlockView, parent).header();
if parent.number() != (header.number() - 1) {
panic!("Unexpected block parent");
}
},
None => {
panic!("Unknown block parent {:?} for block {}", header.parent_hash(), number);
}
}
}
let len = self.numbers.read().len();
if number == len {
{
let mut difficulty = self.difficulty.write();
*difficulty = *difficulty + header.difficulty().clone();
}
mem::replace(&mut *self.last_hash.write(), h.clone());
self.blocks.write().insert(h.clone(), b);
self.numbers.write().insert(number, h.clone());
let mut parent_hash = header.parent_hash().clone();
if number > 0 {
let mut n = number - 1;
while n > 0 && self.numbers.read()[&n] != parent_hash {
*self.numbers.write().get_mut(&n).unwrap() = parent_hash.clone();
n -= 1;
parent_hash = view!(BlockView, &self.blocks.read()[&parent_hash]).header().parent_hash().clone();
}
}
}
else {
self.blocks.write().insert(h.clone(), b.to_vec());
}
Ok(h)
}
}
impl Call for TestBlockChainClient {
// State will not be used by test client anyway, since all methods that accept state are mocked
type State = ();
fn call(&self, _t: &SignedTransaction, _analytics: CallAnalytics, _state: &mut Self::State, _header: &Header) -> Result<Executed, CallError> {
impl BlockChainClient for TestBlockChainClient {
fn call(&self, _t: &SignedTransaction, _analytics: CallAnalytics, _block: BlockId) -> Result<Executed, CallError> {
self.execution_result.read().clone().unwrap()
}
fn call_many(&self, txs: &[(SignedTransaction, CallAnalytics)], state: &mut Self::State, header: &Header) -> Result<Vec<Executed>, CallError> {
fn call_many(&self, txs: &[(SignedTransaction, CallAnalytics)], block: BlockId) -> Result<Vec<Executed>, CallError> {
let mut res = Vec::with_capacity(txs.len());
for &(ref tx, analytics) in txs {
res.push(self.call(tx, analytics, state, header)?);
res.push(self.call(tx, analytics, block)?);
}
Ok(res)
}
fn estimate_gas(&self, _t: &SignedTransaction, _state: &Self::State, _header: &Header) -> Result<U256, CallError> {
fn estimate_gas(&self, _t: &SignedTransaction, _block: BlockId) -> Result<U256, CallError> {
Ok(21000.into())
}
}
impl StateInfo for () {
fn nonce(&self, _address: &Address) -> trie::Result<U256> { unimplemented!() }
fn balance(&self, _address: &Address) -> trie::Result<U256> { unimplemented!() }
fn storage_at(&self, _address: &Address, _key: &H256) -> trie::Result<H256> { unimplemented!() }
fn code(&self, _address: &Address) -> trie::Result<Option<Arc<Bytes>>> { unimplemented!() }
}
impl StateClient for TestBlockChainClient {
// State will not be used by test client anyway, since all methods that accept state are mocked
type State = ();
fn latest_state(&self) -> Self::State {
()
}
fn state_at(&self, _id: BlockId) -> Option<Self::State> {
Some(())
}
}
impl EngineInfo for TestBlockChainClient {
fn engine(&self) -> &EthEngine {
unimplemented!()
}
}
impl BlockChainClient for TestBlockChainClient {
fn replay(&self, _id: TransactionId, _analytics: CallAnalytics) -> Result<Executed, CallError> {
self.execution_result.read().clone().unwrap()
}
@@ -623,20 +439,49 @@ impl BlockChainClient for TestBlockChainClient {
Self::block_hash(self, id)
}
fn storage_root(&self, _address: &Address, _id: BlockId) -> Option<H256> {
None
}
fn code(&self, address: &Address, state: StateOrBlock) -> Option<Option<Bytes>> {
match state {
StateOrBlock::Block(BlockId::Latest) => Some(self.code.read().get(address).cloned()),
fn nonce(&self, address: &Address, id: BlockId) -> Option<U256> {
match id {
BlockId::Latest | BlockId::Pending => Some(self.nonces.read().get(address).cloned().unwrap_or(self.spec.params().account_start_nonce)),
_ => None,
}
}
fn storage_at(&self, address: &Address, position: &H256, state: StateOrBlock) -> Option<H256> {
match state {
StateOrBlock::Block(BlockId::Latest) => Some(self.storage.read().get(&(address.clone(), position.clone())).cloned().unwrap_or_else(H256::new)),
fn storage_root(&self, _address: &Address, _id: BlockId) -> Option<H256> {
None
}
fn latest_nonce(&self, address: &Address) -> U256 {
self.nonce(address, BlockId::Latest).unwrap()
}
fn code(&self, address: &Address, id: BlockId) -> Option<Option<Bytes>> {
match id {
BlockId::Latest | BlockId::Pending => Some(self.code.read().get(address).cloned()),
_ => None,
}
}
fn code_hash(&self, address: &Address, id: BlockId) -> Option<H256> {
match id {
BlockId::Latest | BlockId::Pending => self.code.read().get(address).map(|c| keccak(&c)),
_ => None,
}
}
fn balance(&self, address: &Address, id: BlockId) -> Option<U256> {
match id {
BlockId::Latest | BlockId::Pending => Some(self.balances.read().get(address).cloned().unwrap_or_else(U256::zero)),
_ => None,
}
}
fn latest_balance(&self, address: &Address) -> U256 {
self.balance(address, BlockId::Latest).unwrap()
}
fn storage_at(&self, address: &Address, position: &H256, id: BlockId) -> Option<H256> {
match id {
BlockId::Latest | BlockId::Pending => Some(self.storage.read().get(&(address.clone(), position.clone())).cloned().unwrap_or_else(H256::new)),
_ => None,
}
}
@@ -652,6 +497,10 @@ impl BlockChainClient for TestBlockChainClient {
None // Simple default.
}
fn transaction_block(&self, _id: TransactionId) -> Option<H256> {
None // Simple default.
}
fn uncle(&self, _id: UncleId) -> Option<encoded::Header> {
None // Simple default.
}
@@ -677,26 +526,36 @@ impl BlockChainClient for TestBlockChainClient {
unimplemented!();
}
fn block_number(&self, id: BlockId) -> Option<BlockNumber> {
match id {
BlockId::Number(number) => Some(number),
BlockId::Earliest => Some(0),
BlockId::Latest => Some(self.chain_info().best_block_number),
BlockId::Hash(ref h) =>
self.numbers.read().iter().find(|&(_, hash)| hash == h).map(|e| *e.0 as u64)
}
fn best_block_header(&self) -> encoded::Header {
self.block_header(BlockId::Hash(self.chain_info().best_block_hash))
.expect("Best block always has header.")
}
fn block_header(&self, id: BlockId) -> Option<encoded::Header> {
self.block_hash(id)
.and_then(|hash| self.blocks.read().get(&hash).map(|r| Rlp::new(r).at(0).as_raw().to_vec()))
.map(encoded::Header::new)
}
fn block_number(&self, _id: BlockId) -> Option<BlockNumber> {
unimplemented!()
}
fn block_body(&self, id: BlockId) -> Option<encoded::Body> {
self.block_hash(id).and_then(|hash| self.blocks.read().get(&hash).map(|r| {
let block = view!(BlockView, r);
let mut stream = RlpStream::new_list(2);
stream.append_raw(block.transactions_rlp().as_raw(), 1);
stream.append_raw(block.uncles_rlp().as_raw(), 1);
stream.append_raw(Rlp::new(r).at(1).as_raw(), 1);
stream.append_raw(Rlp::new(r).at(2).as_raw(), 1);
encoded::Body::new(stream.out())
}))
}
fn block(&self, id: BlockId) -> Option<encoded::Block> {
self.block_hash(id)
.and_then(|hash| self.blocks.read().get(&hash).cloned())
.map(encoded::Block::new)
}
fn block_extra_info(&self, id: BlockId) -> Option<BTreeMap<String, String>> {
self.block(id)
.map(|block| block.view().header())
@@ -709,6 +568,7 @@ impl BlockChainClient for TestBlockChainClient {
BlockId::Number(number) if (number as usize) < self.blocks.read().len() => BlockStatus::InChain,
BlockId::Hash(ref hash) if self.blocks.read().get(hash).is_some() => BlockStatus::InChain,
BlockId::Latest | BlockId::Earliest => BlockStatus::InChain,
BlockId::Pending => BlockStatus::Pending,
_ => BlockStatus::Unknown,
}
}
@@ -772,6 +632,55 @@ impl BlockChainClient for TestBlockChainClient {
None
}
fn import_block(&self, b: Bytes) -> Result<H256, BlockImportError> {
let header = Rlp::new(&b).val_at::<BlockHeader>(0);
let h = header.hash();
let number: usize = header.number() as usize;
if number > self.blocks.read().len() {
panic!("Unexpected block number. Expected {}, got {}", self.blocks.read().len(), number);
}
if number > 0 {
match self.blocks.read().get(header.parent_hash()) {
Some(parent) => {
let parent = Rlp::new(parent).val_at::<BlockHeader>(0);
if parent.number() != (header.number() - 1) {
panic!("Unexpected block parent");
}
},
None => {
panic!("Unknown block parent {:?} for block {}", header.parent_hash(), number);
}
}
}
let len = self.numbers.read().len();
if number == len {
{
let mut difficulty = self.difficulty.write();
*difficulty = *difficulty + header.difficulty().clone();
}
mem::replace(&mut *self.last_hash.write(), h.clone());
self.blocks.write().insert(h.clone(), b);
self.numbers.write().insert(number, h.clone());
let mut parent_hash = header.parent_hash().clone();
if number > 0 {
let mut n = number - 1;
while n > 0 && self.numbers.read()[&n] != parent_hash {
*self.numbers.write().get_mut(&n).unwrap() = parent_hash.clone();
n -= 1;
parent_hash = Rlp::new(&self.blocks.read()[&parent_hash]).val_at::<BlockHeader>(0).parent_hash().clone();
}
}
}
else {
self.blocks.write().insert(h.clone(), b.to_vec());
}
Ok(h)
}
fn import_block_with_receipts(&self, b: Bytes, _r: Bytes) -> Result<H256, BlockImportError> {
self.import_block(b)
}
fn queue_info(&self) -> QueueInfo {
QueueInfo {
verified_queue_size: self.queue_size.load(AtomicOrder::Relaxed),
@@ -790,6 +699,22 @@ impl BlockChainClient for TestBlockChainClient {
Default::default()
}
fn chain_info(&self) -> BlockChainInfo {
let number = self.blocks.read().len() as BlockNumber - 1;
BlockChainInfo {
total_difficulty: *self.difficulty.read(),
pending_total_difficulty: *self.difficulty.read(),
genesis_hash: self.genesis_hash.clone(),
best_block_hash: self.last_hash.read().clone(),
best_block_number: number,
best_block_timestamp: number,
first_block_hash: self.first_block.read().as_ref().map(|x| x.0),
first_block_number: self.first_block.read().as_ref().map(|x| x.1),
ancient_block_hash: self.ancient_block.read().as_ref().map(|x| x.0),
ancient_block_number: self.ancient_block.read().as_ref().map(|x| x.1)
}
}
fn filter_traces(&self, _filter: TraceFilter) -> Option<Vec<LocalizedTrace>> {
self.traces.read().clone()
}
@@ -806,8 +731,19 @@ impl BlockChainClient for TestBlockChainClient {
self.traces.read().clone()
}
fn ready_transactions(&self) -> Vec<Arc<VerifiedTransaction>> {
self.miner.ready_transactions(self)
fn queue_transactions(&self, transactions: Vec<Bytes>, _peer_id: usize) {
// import right here
let txs = transactions.into_iter().filter_map(|bytes| UntrustedRlp::new(&bytes).as_val().ok()).collect();
self.miner.import_external_transactions(self, txs);
}
fn queue_consensus_message(&self, message: Bytes) {
self.spec.engine.handle_message(&message).unwrap();
}
fn ready_transactions(&self) -> Vec<PendingTransaction> {
let info = self.chain_info();
self.miner.ready_transactions(info.best_block_number, info.best_block_timestamp)
}
fn signing_chain_id(&self) -> Option<u64> { None }
@@ -820,7 +756,7 @@ impl BlockChainClient for TestBlockChainClient {
fn set_spec_name(&self, _: String) { unimplemented!(); }
fn disable(&self) { self.disabled.store(true, AtomicOrder::Relaxed); }
fn disable(&self) { unimplemented!(); }
fn pruning_info(&self) -> PruningInfo {
let best_num = self.chain_info().best_block_number;
@@ -830,9 +766,11 @@ impl BlockChainClient for TestBlockChainClient {
}
}
fn transact_contract(&self, address: Address, data: Bytes) -> Result<(), transaction::Error> {
fn call_contract(&self, _id: BlockId, _address: Address, _data: Bytes) -> Result<Bytes, String> { Ok(vec![]) }
fn transact_contract(&self, address: Address, data: Bytes) -> Result<transaction::ImportResult, EthcoreError> {
let transaction = Transaction {
nonce: self.latest_nonce(&self.miner.authoring_params().author),
nonce: self.latest_nonce(&self.miner.author()),
action: Action::Call(address),
gas: self.spec.gas_limit,
gas_price: U256::zero(),
@@ -847,25 +785,11 @@ impl BlockChainClient for TestBlockChainClient {
fn registrar_address(&self) -> Option<Address> { None }
fn registry_address(&self, _name: String, _block: BlockId) -> Option<Address> { None }
fn eip86_transition(&self) -> u64 { u64::max_value() }
}
impl IoClient for TestBlockChainClient {
fn queue_transactions(&self, transactions: Vec<Bytes>, _peer_id: usize) {
// import right here
let txs = transactions.into_iter().filter_map(|bytes| Rlp::new(&bytes).as_val().ok()).collect();
self.miner.import_external_transactions(self, txs);
}
fn queue_ancient_block(&self, b: Bytes, _r: Bytes) -> Result<H256, BlockImportError> {
self.import_block(b)
}
fn queue_consensus_message(&self, message: Bytes) {
self.spec.engine.handle_message(&message).unwrap();
}
}
impl ProvingBlockChainClient for TestBlockChainClient {
fn prove_storage(&self, _: H256, _: H256, _: BlockId) -> Option<(Vec<Bytes>, H256)> {
None
@@ -890,9 +814,8 @@ impl super::traits::EngineClient for TestBlockChainClient {
}
fn submit_seal(&self, block_hash: H256, seal: Vec<Bytes>) {
let import = self.miner.submit_seal(block_hash, seal).and_then(|block| self.import_sealed_block(block));
if let Err(err) = import {
warn!(target: "poa", "Wrong internal seal submission! {:?}", err);
if self.miner.submit_seal(self, block_hash, seal).is_err() {
warn!(target: "poa", "Wrong internal seal submission!")
}
}
@@ -902,6 +825,10 @@ impl super::traits::EngineClient for TestBlockChainClient {
None
}
fn chain_info(&self) -> BlockChainInfo {
BlockChainClient::chain_info(self)
}
fn as_full_client(&self) -> Option<&BlockChainClient> { Some(self) }
fn block_number(&self, id: BlockId) -> Option<BlockNumber> {

View File

@@ -15,30 +15,25 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::collections::BTreeMap;
use std::sync::Arc;
use itertools::Itertools;
use block::{OpenBlock, SealedBlock, ClosedBlock};
use blockchain::TreeRoute;
use encoded;
use vm::LastHashes;
use error::{ImportResult, CallError, BlockImportError};
use error::{ImportResult, CallError, Error as EthcoreError, BlockImportError};
use evm::Schedule;
use factory::VmFactory;
use executive::Executed;
use filter::Filter;
use header::{BlockNumber};
use log_entry::LocalizedLogEntry;
use receipt::LocalizedReceipt;
use trace::LocalizedTrace;
use transaction::{self, LocalizedTransaction, SignedTransaction};
use transaction::{LocalizedTransaction, PendingTransaction, SignedTransaction, ImportResult as TransactionImportResult};
use verification::queue::QueueInfo as BlockQueueInfo;
use state::StateInfo;
use header::Header;
use engines::EthEngine;
use ethereum_types::{H256, U256, Address};
use ethcore_miner::pool::VerifiedTransaction;
use bytes::Bytes;
use hashdb::DBValue;
@@ -51,168 +46,12 @@ use types::block_status::BlockStatus;
use types::mode::Mode;
use types::pruning_info::PruningInfo;
/// State information to be used during client query
pub enum StateOrBlock {
/// State to be used, may be pending
State(Box<StateInfo>),
/// Blockchain database client. Owns and manages a blockchain and a block queue.
pub trait BlockChainClient : Sync + Send {
/// Id of an existing block from a chain to get state from
Block(BlockId)
}
impl<S: StateInfo + 'static> From<S> for StateOrBlock {
fn from(info: S) -> StateOrBlock {
StateOrBlock::State(Box::new(info) as Box<_>)
}
}
impl From<Box<StateInfo>> for StateOrBlock {
fn from(info: Box<StateInfo>) -> StateOrBlock {
StateOrBlock::State(info)
}
}
impl From<BlockId> for StateOrBlock {
fn from(id: BlockId) -> StateOrBlock {
StateOrBlock::Block(id)
}
}
/// Provides `nonce` and `latest_nonce` methods
pub trait Nonce {
/// Attempt to get address nonce at given block.
/// May not fail on BlockId::Latest.
fn nonce(&self, address: &Address, id: BlockId) -> Option<U256>;
/// Get address nonce at the latest block's state.
fn latest_nonce(&self, address: &Address) -> U256 {
self.nonce(address, BlockId::Latest)
.expect("nonce will return Some when given BlockId::Latest. nonce was given BlockId::Latest. \
Therefore nonce has returned Some; qed")
}
}
/// Provides `balance` and `latest_balance` methods
pub trait Balance {
/// Get address balance at the given block's state.
///
/// May not return None if given BlockId::Latest.
/// Returns None if and only if the block's root hash has been pruned from the DB.
fn balance(&self, address: &Address, state: StateOrBlock) -> Option<U256>;
/// Get address balance at the latest block's state.
fn latest_balance(&self, address: &Address) -> U256 {
self.balance(address, BlockId::Latest.into())
.expect("balance will return Some if given BlockId::Latest. balance was given BlockId::Latest \
Therefore balance has returned Some; qed")
}
}
/// Provides methods to access account info
pub trait AccountData: Nonce + Balance {}
/// Provides `chain_info` method
pub trait ChainInfo {
/// Get blockchain information.
fn chain_info(&self) -> BlockChainInfo;
}
/// Provides various information on a block by it's ID
pub trait BlockInfo {
/// Get raw block header data by block id.
fn block_header(&self, id: BlockId) -> Option<encoded::Header>;
/// Get the best block header.
fn best_block_header(&self) -> Header;
/// Get raw block data by block header hash.
fn block(&self, id: BlockId) -> Option<encoded::Block>;
/// Get address code hash at given block's state.
fn code_hash(&self, address: &Address, id: BlockId) -> Option<H256>;
}
/// Provides various information on a transaction by it's ID
pub trait TransactionInfo {
/// Get the hash of block that contains the transaction, if any.
fn transaction_block(&self, id: TransactionId) -> Option<H256>;
}
/// Provides methods to access chain state
pub trait StateClient {
/// Type representing chain state
type State: StateInfo;
/// Get a copy of the best block's state.
fn latest_state(&self) -> Self::State;
/// Attempt to get a copy of a specific block's final state.
///
/// This will not fail if given BlockId::Latest.
/// Otherwise, this can fail (but may not) if the DB prunes state or the block
/// is unknown.
fn state_at(&self, id: BlockId) -> Option<Self::State>;
}
/// Provides various blockchain information, like block header, chain state etc.
pub trait BlockChain: ChainInfo + BlockInfo + TransactionInfo {}
/// Provides information on a blockchain service and it's registry
pub trait RegistryInfo {
/// Get the address of a particular blockchain service, if available.
fn registry_address(&self, name: String, block: BlockId) -> Option<Address>;
}
// FIXME Why these methods belong to BlockChainClient and not MiningBlockChainClient?
/// Provides methods to import block into blockchain
pub trait ImportBlock {
/// Import a block into the blockchain.
fn import_block(&self, bytes: Bytes) -> Result<H256, BlockImportError>;
}
/// Provides `call_contract` method
pub trait CallContract {
/// Like `call`, but with various defaults. Designed to be used for calling contracts.
fn call_contract(&self, id: BlockId, address: Address, data: Bytes) -> Result<Bytes, String>;
}
/// Provides `call` and `call_many` methods
pub trait Call {
/// Type representing chain state
type State: StateInfo;
/// Makes a non-persistent transaction call.
fn call(&self, tx: &SignedTransaction, analytics: CallAnalytics, state: &mut Self::State, header: &Header) -> Result<Executed, CallError>;
/// Makes multiple non-persistent but dependent transaction calls.
/// Returns a vector of successes or a failure if any of the transaction fails.
fn call_many(&self, txs: &[(SignedTransaction, CallAnalytics)], state: &mut Self::State, header: &Header) -> Result<Vec<Executed>, CallError>;
/// Estimates how much gas will be necessary for a call.
fn estimate_gas(&self, t: &SignedTransaction, state: &Self::State, header: &Header) -> Result<U256, CallError>;
}
/// Provides `engine` method
pub trait EngineInfo {
/// Get underlying engine object
fn engine(&self) -> &EthEngine;
}
/// IO operations that should off-load heavy work to another thread.
pub trait IoClient: Sync + Send {
/// Queue transactions for importing.
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: Bytes, receipts_bytes: Bytes) -> Result<H256, BlockImportError>;
/// Queue conensus engine message.
fn queue_consensus_message(&self, message: Bytes);
}
/// Blockchain database client. Owns and manages a blockchain and a block queue.
pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContract + RegistryInfo + ImportBlock
+ IoClient {
/// Look up the block number for the given block ID.
fn block_number(&self, id: BlockId) -> Option<BlockNumber>;
@@ -220,39 +59,67 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra
/// Block body is an RLP list of two items: uncles and transactions.
fn block_body(&self, id: BlockId) -> Option<encoded::Body>;
/// Get raw block data by block header hash.
fn block(&self, id: BlockId) -> Option<encoded::Block>;
/// Get block status by block header hash.
fn block_status(&self, id: BlockId) -> BlockStatus;
/// Get block total difficulty.
fn block_total_difficulty(&self, id: BlockId) -> Option<U256>;
/// Attempt to get address nonce at given block.
/// May not fail on BlockId::Latest.
fn nonce(&self, address: &Address, id: BlockId) -> Option<U256>;
/// Attempt to get address storage root at given block.
/// May not fail on BlockId::Latest.
fn storage_root(&self, address: &Address, id: BlockId) -> Option<H256>;
/// Get address nonce at the latest block's state.
fn latest_nonce(&self, address: &Address) -> U256 {
self.nonce(address, BlockId::Latest)
.expect("nonce will return Some when given BlockId::Latest. nonce was given BlockId::Latest. \
Therefore nonce has returned Some; qed")
}
/// Get block hash.
fn block_hash(&self, id: BlockId) -> Option<H256>;
/// Get address code at given block's state.
fn code(&self, address: &Address, state: StateOrBlock) -> Option<Option<Bytes>>;
fn code(&self, address: &Address, id: BlockId) -> Option<Option<Bytes>>;
/// Get address code at the latest block's state.
fn latest_code(&self, address: &Address) -> Option<Bytes> {
self.code(address, BlockId::Latest.into())
self.code(address, BlockId::Latest)
.expect("code will return Some if given BlockId::Latest; qed")
}
/// Get address code hash at given block's state.
fn code_hash(&self, address: &Address, id: BlockId) -> Option<H256>;
/// Get address balance at the given block's state.
///
/// May not return None if given BlockId::Latest.
/// Returns None if and only if the block's root hash has been pruned from the DB.
fn balance(&self, address: &Address, id: BlockId) -> Option<U256>;
/// Get address balance at the latest block's state.
fn latest_balance(&self, address: &Address) -> U256 {
self.balance(address, BlockId::Latest)
.expect("balance will return Some if given BlockId::Latest. balance was given BlockId::Latest \
Therefore balance has returned Some; qed")
}
/// Get value of the storage at given position at the given block's state.
///
/// May not return None if given BlockId::Latest.
/// Returns None if and only if the block's root hash has been pruned from the DB.
fn storage_at(&self, address: &Address, position: &H256, state: StateOrBlock) -> Option<H256>;
fn storage_at(&self, address: &Address, position: &H256, id: BlockId) -> Option<H256>;
/// Get value of the storage at given position at the latest block's state.
fn latest_storage_at(&self, address: &Address, position: &H256) -> H256 {
self.storage_at(address, position, BlockId::Latest.into())
self.storage_at(address, position, BlockId::Latest)
.expect("storage_at will return Some if given BlockId::Latest. storage_at was given BlockId::Latest. \
Therefore storage_at has returned Some; qed")
}
@@ -268,6 +135,9 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra
/// Get transaction with given hash.
fn transaction(&self, id: TransactionId) -> Option<LocalizedTransaction>;
/// Get the hash of block that contains the transaction, if any.
fn transaction_block(&self, id: TransactionId) -> Option<H256>;
/// Get uncle with given id.
fn uncle(&self, id: UncleId) -> Option<encoded::Header>;
@@ -287,18 +157,40 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra
/// Get raw block receipts data by block header hash.
fn block_receipts(&self, hash: &H256) -> Option<Bytes>;
/// Import a block into the blockchain.
fn import_block(&self, bytes: Bytes) -> Result<H256, BlockImportError>;
/// Import a block with transaction receipts. Does no sealing and transaction validation.
fn import_block_with_receipts(&self, block_bytes: Bytes, receipts_bytes: Bytes) -> Result<H256, BlockImportError>;
/// Get block queue information.
fn queue_info(&self) -> BlockQueueInfo;
/// Clear block queue and abort all import activity.
fn clear_queue(&self);
/// Get blockchain information.
fn chain_info(&self) -> BlockChainInfo;
/// Get the registrar address, if it exists.
fn additional_params(&self) -> BTreeMap<String, String>;
/// Get the best block header.
fn best_block_header(&self) -> encoded::Header;
/// Returns logs matching given filter.
fn logs(&self, filter: Filter) -> Vec<LocalizedLogEntry>;
/// Makes a non-persistent transaction call.
fn call(&self, tx: &SignedTransaction, analytics: CallAnalytics, block: BlockId) -> Result<Executed, CallError>;
/// Makes multiple non-persistent but dependent transaction calls.
/// Returns a vector of successes or a failure if any of the transaction fails.
fn call_many(&self, txs: &[(SignedTransaction, CallAnalytics)], block: BlockId) -> Result<Vec<Executed>, CallError>;
/// Estimates how much gas will be necessary for a call.
fn estimate_gas(&self, t: &SignedTransaction, block: BlockId) -> Result<U256, CallError>;
/// Replays a given transaction for inspection.
fn replay(&self, t: TransactionId, analytics: CallAnalytics) -> Result<Executed, CallError>;
@@ -320,8 +212,14 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra
/// Get last hashes starting from best block.
fn last_hashes(&self) -> LastHashes;
/// Queue transactions for importing.
fn queue_transactions(&self, transactions: Vec<Bytes>, peer_id: usize);
/// Queue conensus engine message.
fn queue_consensus_message(&self, message: Bytes);
/// List all transactions that are allowed into the next block.
fn ready_transactions(&self) -> Vec<Arc<VerifiedTransaction>>;
fn ready_transactions(&self) -> Vec<PendingTransaction>;
/// Sorted list of transaction gas prices from at least last sample_size blocks.
fn gas_price_corpus(&self, sample_size: usize) -> ::stats::Corpus<U256> {
@@ -372,58 +270,52 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra
/// Returns information about pruning/data availability.
fn pruning_info(&self) -> PruningInfo;
/// Schedule state-altering transaction to be executed on the next pending block.
fn transact_contract(&self, address: Address, data: Bytes) -> Result<(), transaction::Error>;
/// Like `call`, but with various defaults. Designed to be used for calling contracts.
fn call_contract(&self, id: BlockId, address: Address, data: Bytes) -> Result<Bytes, String>;
/// Import a transaction: used for misbehaviour reporting.
fn transact_contract(&self, address: Address, data: Bytes) -> Result<TransactionImportResult, EthcoreError>;
/// Get the address of the registry itself.
fn registrar_address(&self) -> Option<Address>;
/// Get the address of a particular blockchain service, if available.
fn registry_address(&self, name: String, block: BlockId) -> Option<Address>;
/// Get the EIP-86 transition block number.
fn eip86_transition(&self) -> u64;
}
/// Provides `reopen_block` method
pub trait ReopenBlock {
/// Reopens an OpenBlock and updates uncles.
fn reopen_block(&self, block: ClosedBlock) -> OpenBlock;
}
/// Provides `prepare_open_block` method
pub trait PrepareOpenBlock {
/// Extended client interface used for mining
pub trait MiningBlockChainClient: BlockChainClient {
/// Returns OpenBlock prepared for closing.
fn prepare_open_block(&self,
author: Address,
gas_range_target: (U256, U256),
extra_data: Bytes
) -> OpenBlock;
}
/// Provides methods used for sealing new state
pub trait BlockProducer: PrepareOpenBlock + ReopenBlock {}
/// Reopens an OpenBlock and updates uncles.
fn reopen_block(&self, block: ClosedBlock) -> OpenBlock;
/// Provides `latest_schedule` method
pub trait ScheduleInfo {
/// Returns latest schedule.
fn latest_schedule(&self) -> Schedule;
}
/// Returns EvmFactory.
fn vm_factory(&self) -> &VmFactory;
///Provides `import_sealed_block` method
pub trait ImportSealedBlock {
/// Import sealed block. Skips all verifications.
fn import_sealed_block(&self, block: SealedBlock) -> ImportResult;
}
/// Provides `broadcast_proposal_block` method
pub trait BroadcastProposalBlock {
/// Broadcast a block proposal.
fn broadcast_proposal_block(&self, block: SealedBlock);
/// Import sealed block. Skips all verifications.
fn import_sealed_block(&self, block: SealedBlock) -> ImportResult;
/// Returns latest schedule.
fn latest_schedule(&self) -> Schedule;
/// Returns base of this trait
fn as_block_chain_client(&self) -> &BlockChainClient;
}
/// Provides methods to import sealed block and broadcast a block proposal
pub trait SealedBlockImporter: ImportSealedBlock + BroadcastProposalBlock {}
/// Client facilities used by internally sealing Engines.
pub trait EngineClient: Sync + Send + ChainInfo {
pub trait EngineClient: Sync + Send {
/// Make a new block and seal it.
fn update_sealing(&self);
@@ -440,6 +332,9 @@ pub trait EngineClient: Sync + Send + ChainInfo {
/// The block corresponding the the parent hash must be stored already.
fn epoch_transition_for(&self, parent_hash: H256) -> Option<::engines::EpochTransition>;
/// Get block chain info.
fn chain_info(&self) -> BlockChainInfo;
/// Attempt to cast the engine client to a full client.
fn as_full_client(&self) -> Option<&BlockChainClient>;

View File

@@ -218,12 +218,15 @@ impl Writable for DBTransaction {
}
impl<KVDB: KeyValueDB + ?Sized> Readable for KVDB {
fn read<T, R>(&self, col: Option<u32>, key: &Key<T, Target = R>) -> Option<T>
where T: rlp::Decodable, R: Deref<Target = [u8]> {
self.get(col, &key.key())
.expect(&format!("db get failed, key: {:?}", &key.key() as &[u8]))
.map(|v| rlp::decode(&v).expect("decode db value failed") )
fn read<T, R>(&self, col: Option<u32>, key: &Key<T, Target = R>) -> Option<T> where T: rlp::Decodable, R: Deref<Target = [u8]> {
let result = self.get(col, &key.key());
match result {
Ok(option) => option.map(|v| rlp::decode(&v)),
Err(err) => {
panic!("db get failed, key: {:?}, err: {:?}", &key.key() as &[u8], err);
}
}
}
fn exists<T, R>(&self, col: Option<u32>, key: &Key<T, Target = R>) -> bool where R: Deref<Target = [u8]> {

View File

@@ -24,13 +24,14 @@
//! decoded object where parts like the hash can be saved.
use block::Block as FullBlock;
use ethereum_types::{H256, Bloom, U256, Address};
use hash::keccak;
use header::{BlockNumber, Header as FullHeader};
use heapsize::HeapSizeOf;
use rlp::{self, Rlp, RlpStream};
use transaction::UnverifiedTransaction;
use views::{self, BlockView, HeaderView, BodyView};
use views;
use hash::keccak;
use heapsize::HeapSizeOf;
use ethereum_types::{H256, Bloom, U256, Address};
use rlp::Rlp;
/// Owning header view.
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -47,13 +48,11 @@ impl Header {
pub fn new(encoded: Vec<u8>) -> Self { Header(encoded) }
/// Upgrade this encoded view to a fully owned `Header` object.
pub fn decode(&self) -> Result<FullHeader, rlp::DecoderError> {
rlp::decode(&self.0)
}
pub fn decode(&self) -> FullHeader { ::rlp::decode(&self.0) }
/// Get a borrowed header view onto the data.
#[inline]
pub fn view(&self) -> HeaderView { view!(HeaderView, &self.0) }
pub fn view(&self) -> views::HeaderView { views::HeaderView::new(&self.0) }
/// Get the rlp of the header.
#[inline]
@@ -126,7 +125,7 @@ impl Body {
/// Get a borrowed view of the data within.
#[inline]
pub fn view(&self) -> BodyView { view!(BodyView, &self.0) }
pub fn view(&self) -> views::BodyView { views::BodyView::new(&self.0) }
/// Fully decode this block body.
pub fn decode(&self) -> (Vec<UnverifiedTransaction>, Vec<FullHeader>) {
@@ -145,9 +144,6 @@ impl Body {
// forwarders to borrowed view.
impl Body {
/// Get raw rlp of transactions
pub fn transactions_rlp(&self) -> Rlp { self.view().transactions_rlp().rlp }
/// Get a vector of all transactions.
pub fn transactions(&self) -> Vec<UnverifiedTransaction> { self.view().transactions() }
@@ -160,9 +156,6 @@ impl Body {
/// The hash of each transaction in the block.
pub fn transaction_hashes(&self) -> Vec<H256> { self.view().transaction_hashes() }
/// Get raw rlp of uncle headers
pub fn uncles_rlp(&self) -> Rlp { self.view().uncles_rlp().rlp }
/// Decode uncle headers.
pub fn uncles(&self) -> Vec<FullHeader> { self.view().uncles() }
@@ -188,31 +181,22 @@ impl Block {
/// Create a new owning block view. The raw bytes passed in must be an rlp-encoded block.
pub fn new(raw: Vec<u8>) -> Self { Block(raw) }
/// Create a new owning block view by concatenating the encoded header and body
pub fn new_from_header_and_body(header: &views::HeaderView, body: &views::BodyView) -> Self {
let mut stream = RlpStream::new_list(3);
stream.append_raw(header.rlp().as_raw(), 1);
stream.append_raw(body.transactions_rlp().as_raw(), 1);
stream.append_raw(body.uncles_rlp().as_raw(), 1);
Block::new(stream.out())
}
/// Get a borrowed view of the whole block.
#[inline]
pub fn view(&self) -> BlockView { view!(BlockView, &self.0) }
pub fn view(&self) -> views::BlockView { views::BlockView::new(&self.0) }
/// Get a borrowed view of the block header.
#[inline]
pub fn header_view(&self) -> HeaderView { self.view().header_view() }
pub fn header_view(&self) -> views::HeaderView { self.view().header_view() }
/// Decode to a full block.
pub fn decode(&self) -> Result<FullBlock, rlp::DecoderError> { rlp::decode(&self.0) }
pub fn decode(&self) -> FullBlock { ::rlp::decode(&self.0) }
/// Decode the header.
pub fn decode_header(&self) -> FullHeader { self.view().rlp().val_at(0) }
pub fn decode_header(&self) -> FullHeader { self.rlp().val_at(0) }
/// Clone the encoded header.
pub fn header(&self) -> Header { Header(self.view().rlp().at(0).as_raw().to_vec()) }
pub fn header(&self) -> Header { Header(self.rlp().at(0).as_raw().to_vec()) }
/// Get the rlp of this block.
#[inline]

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