Compare commits

..

1 Commits

Author SHA1 Message Date
Denis S. Soldatov aka General-Beck
6c58fdb3a6 gitlab cache
it is necessary to test
2018-02-16 22:45:29 +03:00
630 changed files with 22619 additions and 56893 deletions

View File

@@ -8,12 +8,14 @@ variables:
CARGOFLAGS: ""
CI_SERVER_NAME: "GitLab CI"
LIBSSL: "libssl1.0.0 (>=1.0.0)"
CARGO_HOME: $CI_PROJECT_DIR/cargo
cache:
key: "$CI_BUILD_STAGE-$CI_BUILD_REF_NAME"
paths:
- target/
- cargo/
untracked: true
linux-ubuntu:
linux-stable:
stage: build
image: parity/rust:gitlab-ci
only:
@@ -31,7 +33,7 @@ linux-ubuntu:
paths:
- parity.zip
name: "stable-x86_64-unknown-linux-gnu_parity"
linux-debian:
linux-stable-debian:
stage: build
image: parity/rust-debian:gitlab-ci
only:
@@ -80,7 +82,6 @@ linux-i686:
paths:
- parity.zip
name: "i686-unknown-linux-gnu"
allow_failure: true
linux-armv7:
stage: build
image: parity/rust-armv7:gitlab-ci
@@ -97,7 +98,6 @@ linux-armv7:
paths:
- parity.zip
name: "armv7_unknown_linux_gnueabihf_parity"
allow_failure: true
linux-arm:
stage: build
image: parity/rust-arm:gitlab-ci
@@ -114,7 +114,6 @@ linux-arm:
paths:
- parity.zip
name: "arm-unknown-linux-gnueabihf_parity"
allow_failure: true
linux-aarch64:
stage: build
image: parity/rust-arm64:gitlab-ci
@@ -133,7 +132,7 @@ linux-aarch64:
name: "aarch64-unknown-linux-gnu_parity"
linux-snap:
stage: build
image: parity/snapcraft:gitlab-ci
image: snapcore/snapcraft:stable
only:
- stable
- beta
@@ -180,35 +179,15 @@ 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
script:
- if [ "$CI_BUILD_REF_NAME" == "master" ]; then DOCKER_TAG="latest"; else DOCKER_TAG=$CI_BUILD_REF_NAME; fi
- if [ "$CI_BUILD_REF_NAME" == "beta-release" ]; then DOCKER_TAG="latest"; else DOCKER_TAG=$CI_BUILD_REF_NAME; fi
- echo "Tag:" $DOCKER_TAG
- docker login -u $Docker_Hub_User_Parity -p $Docker_Hub_Pass_Parity
- scripts/docker-build.sh $DOCKER_TAG

View File

@@ -1,273 +1,341 @@
## Parity [v1.10.2](https://github.com/paritytech/parity/releases/tag/v1.10.2) (2018-04-24)
## Parity [v1.9.2](https://github.com/paritytech/parity/releases/tag/v1.9.2) (2018-02-02)
Parity 1.10.2 is a bug-fix release to improve performance and stability.
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:
- 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 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.10.1](https://github.com/paritytech/parity/releases/tag/v1.10.1) (2018-04-17)
## Parity [v1.9.1](https://github.com/paritytech/parity/releases/tag/v1.9.1) (2018-02-01)
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.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:
- 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.
- 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)

2530
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.8"
version = "1.10.0"
license = "GPL-3.0"
authors = ["Parity Technologies <admin@parity.io>"]
@@ -14,36 +14,38 @@ 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"
serde_derive = "1.0"
app_dirs = "1.1.1"
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 +64,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 +79,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,7 +98,7 @@ ui-precompiled = [
]
ui-enabled = ["dapps"]
dapps = ["parity-dapps"]
miner-debug = ["ethcore/miner-debug"]
jit = ["ethcore/jit"]
json-tests = ["ethcore/json-tests"]
test-heavy = ["ethcore/test-heavy"]
evm-debug = ["ethcore/evm-debug"]
@@ -124,6 +122,7 @@ panic = "abort"
[workspace]
members = [
"chainspec",
"dapps/js-glue",
"ethcore/wasm/run",
"ethcore/types",
"ethkey/cli",
@@ -132,8 +131,4 @@ members = [
"miner",
"transaction-pool",
"whisper",
"whisper/cli",
]
[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,23 +22,21 @@ 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" }
parity-reactor = { path = "../util/reactor" }
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

@@ -19,10 +19,9 @@ use std::{fs, fmt};
use std::io::{self, Read, Write};
use std::path::PathBuf;
use ethereum_types::H256;
use fetch;
use fetch::{self, Mime};
use futures_cpupool::CpuPool;
use hash::keccak_pipe;
use mime_guess::Mime;
use hash::keccak_buffer;
use apps::manifest::{MANIFEST_FILENAME, deserialize_manifest, serialize_manifest, Manifest};
use handlers::{ContentValidator, ValidatorResponse};
@@ -54,16 +53,16 @@ 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()?;
let mut reader = io::BufReader::new(response);
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 +265,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

@@ -216,7 +216,6 @@ impl<R: URLHint + 'static, F: Fetch> Endpoint for ContentFetcher<F, R> {
),
self.embeddable_on.clone(),
self.fetch.clone(),
self.pool.clone(),
)
},
URLHintResult::GithubDapp(content) => {
@@ -233,7 +232,6 @@ impl<R: URLHint + 'static, F: Fetch> Endpoint for ContentFetcher<F, R> {
),
self.embeddable_on.clone(),
self.fetch.clone(),
self.pool.clone(),
)
},
URLHintResult::Content(content) => {
@@ -250,7 +248,6 @@ impl<R: URLHint + 'static, F: Fetch> Endpoint for ContentFetcher<F, R> {
),
self.embeddable_on.clone(),
self.fetch.clone(),
self.pool.clone(),
)
},
};
@@ -283,7 +280,7 @@ impl<R: URLHint + 'static, F: Fetch> Endpoint for ContentFetcher<F, R> {
mod tests {
use std::env;
use std::sync::Arc;
use fetch::Client;
use fetch::{Fetch, Client};
use futures::{future, Future};
use hash_fetch::urlhint::{URLHint, URLHintResult};
use ethereum_types::H256;

View File

@@ -23,6 +23,8 @@ use page;
use proxypac::ProxyPac;
use web::Web;
use fetch::Fetch;
use parity_dapps::WebApp;
use parity_ui;
use {WebProxyTokens, ParentFrameSettings};
mod app;
@@ -42,15 +44,11 @@ pub const WEB_PATH: &'static str = "web";
pub const URL_REFERER: &'static str = "__referer=";
pub fn utils(pool: CpuPool) -> Box<Endpoint> {
Box::new(page::builtin::Dapp::new(pool, ::parity_ui::App::default()))
Box::new(page::builtin::Dapp::new(pool, parity_ui::App::default()))
}
pub fn ui(pool: CpuPool) -> Box<Endpoint> {
Box::new(page::builtin::Dapp::with_fallback_to_index(pool, ::parity_ui::App::default()))
}
pub fn ui_deprecation(pool: CpuPool) -> Box<Endpoint> {
Box::new(page::builtin::Dapp::with_fallback_to_index(pool, ::parity_ui_deprecation::App::default()))
Box::new(page::builtin::Dapp::with_fallback_to_index(pool, parity_ui::App::default()))
}
pub fn ui_redirection(embeddable: Option<ParentFrameSettings>) -> Box<Endpoint> {
@@ -78,28 +76,25 @@ pub fn all_endpoints<F: Fetch>(
}
// NOTE [ToDr] Dapps will be currently embeded on 8180
pages.insert(
"ui".into(),
Box::new(page::builtin::Dapp::new_safe_to_embed(pool.clone(), ::parity_ui::App::default(), embeddable.clone()))
);
insert::<parity_ui::App>(&mut pages, "ui", Embeddable::Yes(embeddable.clone()), pool.clone());
// old version
pages.insert(
"v1".into(),
Box::new({
let mut page = page::builtin::Dapp::new_safe_to_embed(pool.clone(), ::parity_ui::old::App::default(), embeddable.clone());
// allow JS eval on old Wallet
page.allow_js_eval();
page
})
);
pages.insert(
"proxy".into(),
ProxyPac::boxed(embeddable.clone(), dapps_domain.to_owned())
);
pages.insert(
WEB_PATH.into(),
Web::boxed(embeddable.clone(), web_proxy_tokens.clone(), fetch.clone(), pool.clone())
);
insert::<parity_ui::old::App>(&mut pages, "v1", Embeddable::Yes(embeddable.clone()), pool.clone());
pages.insert("proxy".into(), ProxyPac::boxed(embeddable.clone(), dapps_domain.to_owned()));
pages.insert(WEB_PATH.into(), Web::boxed(embeddable.clone(), web_proxy_tokens.clone(), fetch.clone()));
(local_endpoints, pages)
}
fn insert<T : WebApp + Default + 'static>(pages: &mut Endpoints, id: &str, embed_at: Embeddable, pool: CpuPool) {
pages.insert(id.to_owned(), Box::new(match embed_at {
Embeddable::Yes(address) => page::builtin::Dapp::new_safe_to_embed(pool, T::default(), address),
Embeddable::No => page::builtin::Dapp::new(pool, T::default()),
}));
}
enum Embeddable {
Yes(Option<ParentFrameSettings>),
#[allow(dead_code)]
No,
}

View File

@@ -23,8 +23,7 @@ use std::time::{Instant, Duration};
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,11 +31,11 @@ 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),
Streaming(StreamingHandler<fetch::BodyReader>),
Streaming(StreamingHandler<fetch::Response>),
}
pub trait ContentValidator: Sized + Send + 'static {
@@ -57,7 +56,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 +192,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(),
)
@@ -253,7 +252,6 @@ impl ContentFetcherHandler {
installer: H,
embeddable_on: Embeddable,
fetch: F,
pool: CpuPool,
) -> Self {
let fetch_control = FetchControl::default();
let errors = Errors { embeddable_on };
@@ -261,10 +259,9 @@ 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,
fetch,
url,
fetch_control.abort.clone(),
@@ -285,7 +282,6 @@ impl ContentFetcherHandler {
}
fn fetch_content<H: ContentValidator, F: Fetch>(
pool: CpuPool,
fetch: F,
url: &str,
abort: Arc<AtomicBool>,
@@ -294,8 +290,8 @@ impl ContentFetcherHandler {
installer: H,
) -> 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 fetch2 = fetch.clone();
let future = fetch.fetch_with_abort(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) {
@@ -307,7 +303,7 @@ impl ContentFetcherHandler {
Ok(ValidatorResponse::Streaming(stream)) => {
trace!(target: "dapps", "Validation OK. Streaming response.");
let (reading, response) = stream.into_response();
pool.spawn(reading).forget();
fetch2.process_and_forget(reading);
FetchState::Streaming(response)
},
Err(e) => {
@@ -323,7 +319,7 @@ impl ContentFetcherHandler {
});
// make sure to run within fetch thread pool.
Box::new(pool2.spawn(future))
fetch.process(future)
}
}

View File

@@ -39,10 +39,8 @@ extern crate node_health;
extern crate parity_dapps_glue as parity_dapps;
extern crate parity_hash_fetch as hash_fetch;
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 +80,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,10 +155,9 @@ 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,
) -> Self {
let content_fetcher = Arc::new(apps::fetcher::ContentFetcher::new(
hash_fetch::urlhint::URLHintContract::new(registrar),
@@ -168,23 +165,6 @@ impl Middleware {
fetch.clone(),
pool.clone(),
).embeddable_on(None).allow_dapps(false));
if info_page_only {
let mut special = HashMap::default();
special.insert(router::SpecialEndpoint::Home, Some(apps::ui_deprecation(pool.clone())));
return Middleware {
endpoints: Default::default(),
router: router::Router::new(
content_fetcher,
None,
special,
None,
dapps_domain.to_owned(),
),
}
}
let special = {
let mut special = special_endpoints(
pool.clone(),
@@ -218,7 +198,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

@@ -75,11 +75,6 @@ impl<T: WebApp + 'static> Dapp<T> {
fallback_to_index_html: false,
}
}
/// Allow the dapp to use `unsafe-eval` to run JS.
pub fn allow_js_eval(&mut self) {
self.info.allow_js_eval = Some(true);
}
}
impl<T: WebApp> Endpoint for Dapp<T> {

View File

@@ -150,20 +150,10 @@ impl Router {
}
},
// RPC by default
_ if self.special.contains_key(&SpecialEndpoint::Rpc) => {
_ => {
trace!(target: "dapps", "Resolving to RPC call.");
Response::None(req)
},
// 404 otherwise
_ => {
Response::Some(Box::new(future::ok(handlers::ContentHandler::error(
hyper::StatusCode::NotFound,
"404 Not Found",
"Requested content was not found.",
None,
self.embeddable_on.clone(),
).into())))
},
}
})
}
}

View File

@@ -14,13 +14,12 @@
// 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::{thread, time};
use std::{io, thread, time};
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};
pub struct FetchControl {
sender: mpsc::Sender<()>,
@@ -34,8 +33,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 +49,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 +96,12 @@ 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 new() -> Result<Self, fetch::Error> where Self: Sized {
Ok(FakeFetch::default())
}
fn fetch_with_abort(&self, url: &str, _abort: fetch::Abort) -> Self::Result {
self.requested.lock().push(url.into());
let manual = self.manual.clone();
let response = self.response.clone();
@@ -109,26 +111,23 @@ impl Fetch for FakeFetch {
// wait for manual resume
let _ = rx.recv();
}
let data = response.lock().take().unwrap_or(b"Some content");
tx.send(fetch::Response::new(u, hyper::Response::new().with_body(data), abort)).unwrap();
let cursor = io::Cursor::new(data);
tx.send(fetch::Response::from_reader(cursor)).unwrap();
});
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)
fn process_and_forget<F, I, E>(&self, f: F) where
F: Future<Item=I, Error=E> + Send + 'static,
I: Send + 'static,
E: Send + 'static,
{
// Spawn the task in a separate thread.
thread::spawn(|| {
let _ = f.wait();
});
}
}

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};
@@ -63,7 +63,7 @@ pub fn init_server<F, B>(process: F, io: IoHandler) -> (Server, Arc<FakeRegistra
let mut dapps_path = env::temp_dir();
dapps_path.push("non-existent-dir-to-prevent-fs-files-from-loading");
let mut builder = ServerBuilder::new(FetchClient::new().unwrap(), &dapps_path, registrar.clone());
let mut builder = ServerBuilder::new(&dapps_path, registrar.clone());
builder.signer_address = Some(("127.0.0.1".into(), SIGNER_PORT));
let server = process(builder).start_unsecured_http(&"127.0.0.1:0".parse().unwrap(), io).unwrap();
(
@@ -144,18 +144,18 @@ 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)>,
allowed_hosts: DomainsValidation<Host>,
fetch: T,
fetch: Option<T>,
serve_ui: bool,
}
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>>(dapps_path: P, registrar: Arc<ContractClient>) -> Self {
ServerBuilder {
dapps_path: dapps_path.as_ref().to_owned(),
registrar: registrar,
@@ -163,7 +163,7 @@ impl ServerBuilder {
web_proxy_tokens: Arc::new(|_| None),
signer_address: None,
allowed_hosts: DomainsValidation::Disabled,
fetch: fetch,
fetch: None,
serve_ui: false,
}
}
@@ -179,7 +179,7 @@ impl<T: Fetch> ServerBuilder<T> {
web_proxy_tokens: self.web_proxy_tokens,
signer_address: self.signer_address,
allowed_hosts: self.allowed_hosts,
fetch: fetch,
fetch: Some(fetch),
serve_ui: self.serve_ui,
}
}
@@ -187,6 +187,7 @@ impl<T: Fetch> ServerBuilder<T> {
/// Asynchronously start server with no authentication,
/// returns result with `Server` handle on success or an error.
pub fn start_unsecured_http(self, addr: &SocketAddr, io: IoHandler) -> io::Result<Server> {
let fetch = self.fetch_client();
Server::start_http(
addr,
io,
@@ -198,10 +199,17 @@ impl<T: Fetch> ServerBuilder<T> {
self.sync_status,
self.web_proxy_tokens,
Remote::new_sync(),
self.fetch,
fetch,
self.serve_ui,
)
}
fn fetch_client(&self) -> T {
match self.fetch.clone() {
Some(fetch) => fetch,
None => T::new().unwrap(),
}
}
}
const DAPPS_DOMAIN: &'static str = "web3.site";
@@ -219,7 +227,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,
@@ -240,7 +248,6 @@ impl Server {
registrar,
sync_status,
fetch,
false,
)
} else {
Middleware::dapps(

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

@@ -25,7 +25,6 @@ use hyper::{mime, StatusCode};
use apps;
use endpoint::{Endpoint, EndpointPath, Request, Response};
use futures::future;
use futures_cpupool::CpuPool;
use handlers::{
ContentFetcherHandler, ContentHandler, ContentValidator, ValidatorResponse,
StreamingHandler,
@@ -36,7 +35,6 @@ pub struct Web<F> {
embeddable_on: Embeddable,
web_proxy_tokens: Arc<WebProxyTokens>,
fetch: F,
pool: CpuPool,
}
impl<F: Fetch> Web<F> {
@@ -44,13 +42,11 @@ impl<F: Fetch> Web<F> {
embeddable_on: Embeddable,
web_proxy_tokens: Arc<WebProxyTokens>,
fetch: F,
pool: CpuPool,
) -> Box<Endpoint> {
Box::new(Web {
embeddable_on,
web_proxy_tokens,
fetch,
pool,
})
}
@@ -133,7 +129,6 @@ impl<F: Fetch> Endpoint for Web<F> {
},
self.embeddable_on.clone(),
self.fetch.clone(),
self.pool.clone(),
))
}
}
@@ -151,7 +146,7 @@ impl ContentValidator for WebInstaller {
let is_html = response.is_html();
let mime = response.content_type().unwrap_or(mime::TEXT_HTML);
let mut handler = StreamingHandler::new(
fetch::BodyReader::new(response),
response,
status,
mime,
self.embeddable_on,

View File

@@ -1,18 +0,0 @@
[package]
description = "Parity UI deprecation notice."
name = "parity-ui-deprecation"
version = "1.10.0"
license = "GPL-3.0"
authors = ["Parity Technologies <admin@parity.io>"]
build = "build.rs"
[features]
default = ["with-syntex", "use-precompiled-js"]
use-precompiled-js = ["parity-dapps-glue/use-precompiled-js"]
with-syntex = ["parity-dapps-glue/with-syntex"]
[build-dependencies]
parity-dapps-glue = "1.9"
[dependencies]
parity-dapps-glue = "1.9"

View File

@@ -1,119 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Parity</title>
<style>
/* 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/>.
*/
:root, :root body {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
background: rgb(95, 95, 95);
color: rgba(255, 255, 255, 0.75);
font-size: 16px;
font-family: 'Roboto', sans-serif;
font-weight: 300;
}
:root a, :root a:visited {
text-decoration: none;
cursor: pointer;
color: rgb(0, 151, 167); /* #f80 */
}
:root a:hover {
color: rgb(0, 174, 193);
}
h1,h2,h3,h4,h5,h6 {
font-weight: 300;
text-transform: uppercase;
text-decoration: none;
}
h1 {
font-size: 24px;
line-height: 36px;
color: rgb(0, 151, 167);
}
h2 {
font-size: 20px;
line-height: 34px;
}
code,kbd,pre,samp {
font-family: 'Roboto Mono', monospace;
}
.parity-navbar {
background: rgb(65, 65, 65);
height: 72px;
padding: 0 1rem;
display: flex;
justify-content: space-between;
}
.parity-status {
clear: both;
padding: 1rem;
margin: 1rem 0;
text-align: right;
opacity: 0.75;
}
.parity-box {
margin: 1rem;
padding: 1rem;
background-color: rgb(48, 48, 48);
box-sizing: border-box;
box-shadow: rgba(0, 0, 0, 0.117647) 0px 1px 6px, rgba(0, 0, 0, 0.117647) 0px 1px 4px;
border-radius: 2px;
z-index: 1;
color: #aaa;
}
.parity-box h1,
.parity-box h2,
.parity-box h3,
.parity-box h4,
.parity-box h5,
.parity-box h6 {
margin: 0;
}
</style>
</head>
<body>
<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>
<p>
</p>
</div>
<div class="parity-status">
</div>
</body>
</html>

View File

@@ -1,55 +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 parity_dapps_glue;
use std::collections::HashMap;
use parity_dapps_glue::{WebApp, File, Info};
#[derive(WebAppFiles)]
#[webapp(path = "../build")]
pub struct App {
pub files: HashMap<&'static str, File>,
}
impl Default for App {
fn default() -> App {
App {
files: Self::files(),
}
}
}
impl WebApp for App {
fn file(&self, path: &str) -> Option<&File> {
self.files.get(path)
}
fn info(&self) -> Info {
Info {
name: "Parity Wallet info page",
version: env!("CARGO_PKG_VERSION"),
author: "Parity <admin@parity.io>",
description: "Deprecation notice for Parity Wallet",
icon_url: "icon.png",
}
}
}
#[test]
fn test_js() {
parity_dapps_glue::js::build(env!("CARGO_MANIFEST_DIR"), "build");
}

View File

@@ -3,17 +3,17 @@ 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]
rustc_version = "0.2"
[dependencies]
parity-ui-dev = { git = "https://github.com/parity-js/shell.git", rev = "eecaadcb9e421bce31e91680d14a20bbd38f92a2", optional = true }
parity-ui-old-dev = { git = "https://github.com/parity-js/dapp-wallet.git", rev = "65deb02e7c007a0fd8aab0c089c93e3fd1de6f87", optional = true }
parity-ui-precompiled = { git = "https://github.com/js-dist-paritytech/parity-master-1-10-shell.git", rev="bd25b41cd642c6b822d820dded3aa601a29aa079", optional = true }
parity-ui-old-precompiled = { git = "https://github.com/js-dist-paritytech/parity-master-1-10-wallet.git", rev="4b6f112412716cd05123d32eeb7fda448288a6c6", optional = true }
parity-ui-dev = { git = "https://github.com/parity-js/shell.git", rev = "2f07ecec53a2319f41e5b83c01073b5386243173", optional = true }
parity-ui-old-dev = { git = "https://github.com/parity-js/dapp-wallet.git", rev = "1a58bf4836c84e1632e27ef607b5a388abd2bf2d", optional = true }
parity-ui-precompiled = { git = "https://github.com/js-dist-paritytech/parity-master-1-10-shell.git", rev="3fb77b61a7f30d6658f81d687e7e415657bd20bd", optional = true }
parity-ui-old-precompiled = { git = "https://github.com/js-dist-paritytech/parity-master-1-10-wallet.git", rev="4c067dfa1a17fe71ab2ca26b18c52dcbd0f4fc04", optional = true }
[features]
no-precompiled-js = ["parity-ui-dev", "parity-ui-old-dev"]

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,29 +0,0 @@
FROM alpine:edge
WORKDIR /build
# install tools and dependencies
RUN apk add --no-cache gcc musl-dev pkgconfig g++ make curl \
eudev-dev rust cargo git file binutils \
libusb-dev linux-headers perl cmake
# show backtraces
ENV RUST_BACKTRACE 1
# show tools
RUN rustc -vV && \
cargo -V && \
gcc -v &&\
g++ -v
# build parity
ADD . /build/parity
RUN cd parity && \
cargo build --release --verbose && \
ls /build/parity/target/release/parity && \
strip /build/parity/target/release/parity
RUN file /build/parity/target/release/parity
EXPOSE 8080 8545 8180
ENTRYPOINT ["/build/parity/target/release/parity"]

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

@@ -3,7 +3,7 @@ WORKDIR /build
# install tools and dependencies
RUN yum -y update&& \
yum install -y git make gcc-c++ gcc file binutils cmake
yum install -y git make gcc-c++ gcc file binutils
# install rustup
RUN curl -sSf https://static.rust-lang.org/rustup.sh -o rustup.sh &&\

View File

@@ -1,4 +1,4 @@
FROM ubuntu:xenial
FROM ubuntu:14.04
MAINTAINER Parity Technologies <devops@parity.io>
WORKDIR /build
#ENV for build TAG
@@ -13,7 +13,6 @@ RUN apt-get update && \
# add-apt-repository
software-properties-common \
make \
cmake \
curl \
wget \
git \
@@ -28,7 +27,20 @@ RUN apt-get update && \
libudev-dev \
pkg-config \
dpkg-dev \
libudev-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
@@ -41,6 +53,7 @@ cd /build&&git clone https://github.com/paritytech/parity && \
git pull&& \
git checkout $BUILD_TAG && \
cargo build --verbose --release --features final && \
#ls /build/parity/target/release/parity && \
strip /build/parity/target/release/parity && \
file /build/parity/target/release/parity&&mkdir -p /parity&& cp /build/parity/target/release/parity /parity&&\
#cleanup Docker image
@@ -51,7 +64,6 @@ cd /build&&git clone https://github.com/paritytech/parity && \
# add-apt-repository
software-properties-common \
make \
cmake \
curl \
wget \
git \
@@ -60,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

@@ -6,7 +6,7 @@ RUN apt-get -y update && \
apt-get install -y --force-yes --no-install-recommends \
curl git make g++ gcc-aarch64-linux-gnu g++-aarch64-linux-gnu \
libc6-arm64-cross libc6-dev-arm64-cross wget file ca-certificates \
binutils-aarch64-linux-gnu cmake \
binutils-aarch64-linux-gnu \
&& \
apt-get clean

View File

@@ -6,7 +6,7 @@ RUN apt-get -y update && \
apt-get install -y --force-yes --no-install-recommends \
curl git make g++ gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf \
libc6-dev-armhf-cross wget file ca-certificates \
binutils-arm-linux-gnueabihf cmake \
binutils-arm-linux-gnueabihf \
&& \
apt-get clean

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

@@ -6,7 +6,6 @@ RUN apt-get update && \
apt-get install -y \
g++ \
build-essential \
cmake \
curl \
git \
file \

View File

@@ -1,44 +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.
The full list of included changes:
- Bump react-qr-reader ([#7941)](https://github.com/paritytech/parity/pull/7941))
- Bump react-qr-reader
- Explicit add webrtc-adapter, non-napa qrcode-generator
- Fix feature=final ([#7914)](https://github.com/paritytech/parity/pull/7914))
- Fix snap build stable ([#7897)](https://github.com/paritytech/parity/pull/7897))
- Backport core PRs to stable ([#7892)](https://github.com/paritytech/parity/pull/7892))
- Update back-references more aggressively after answering from cache ([#7578)](https://github.com/paritytech/parity/pull/7578))
- Store updater metadata in a single place ([#7832)](https://github.com/paritytech/parity/pull/7832))
- 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))
- Backport Master CI PRs to Stable ([#7889)](https://github.com/paritytech/parity/pull/7889))
- 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))
- Bump stable to 1.8.10
- Make track stable
## Parity [v1.8.9](https://github.com/paritytech/parity/releases/tag/v1.8.9) (2018-02-02)
Parity 1.8.9 is a bug-fix release to improve performance and stability. It restores ERC-20 token balances and adds additional bootnodes for the Ropsten test network.

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"
@@ -41,55 +39,43 @@ 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" }
trace-time = { path = "../util/trace-time" }
time = "0.1"
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" }
[dev-dependencies]
tempdir = "0.3"
trie-standardmap = { path = "../util/trie-standardmap" }
kvdb-rocksdb = { path = "../util/kvdb-rocksdb" }
[features]
# Disables seal verification for mined blocks.
# This allows you to submit any seal via RPC to test and benchmark
# how fast pending block get's created while running on the mainnet.
miner-debug = []
# Display EVM debug traces.
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,4 +1,4 @@
// 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
@@ -16,16 +16,18 @@
#![feature(test)]
extern crate bn;
extern crate ethereum_types;
extern crate ethkey;
extern crate parity_crypto;
extern crate rand;
extern crate rustc_hex;
extern crate test;
extern crate ethcore_util as util;
extern crate rand;
extern crate bn;
extern crate crypto;
extern crate ethkey;
extern crate rustc_hex;
extern crate ethcore_bigint;
use self::test::{Bencher};
use rand::{StdRng};
use self::test::Bencher;
use rand::StdRng;
#[bench]
fn bn_128_pairing(b: &mut Bencher) {
@@ -59,12 +61,16 @@ fn bn_128_mul(b: &mut Bencher) {
#[bench]
fn sha256(b: &mut Bencher) {
use parity_crypto::digest::sha256;
use crypto::sha2::Sha256;
use crypto::digest::Digest;
let input = [0_u8; 256];
let mut input: [u8; 256] = [0; 256];
let mut out = [0; 32];
b.iter(|| {
sha256(&input);
let mut sha = Sha256::new();
sha.input(&input);
sha.result(&mut input[0..32]);
});
}
@@ -72,7 +78,7 @@ fn sha256(b: &mut Bencher) {
fn ecrecover(b: &mut Bencher) {
use rustc_hex::FromHex;
use ethkey::{Signature, recover as ec_recover};
use ethereum_types::H256;
use ethcore_bigint::hash::H256;
let input = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b650acf9d3f5f0a2c799776a1254355d5f4061762a237396a99a0e0e3fc2bcd6729514a0dacb2e623ac4abd157cb18163ff942280db4d5caad66ddf941ba12e03").unwrap();
let hash = H256::from_slice(&input[0..32]);
let v = H256::from_slice(&input[32..64]);
@@ -89,3 +95,4 @@ fn ecrecover(b: &mut Bencher) {
let _ = ec_recover(&s, &hash);
});
}

View File

@@ -1,16 +0,0 @@
[package]
name = "ethcore-crypto"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
rust-crypto = "0.2.36"
tiny-keccak = "1.3"
eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1", optional = true }
ethkey = { path = "../../ethkey", optional = true }
ethereum-types = "0.3"
subtle = "0.5"
[features]
default = ["secp256k1"]
secp256k1 = ["eth-secp256k1", "ethkey"]

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,7 +32,24 @@ pub struct Factory {
impl Factory {
/// Create fresh instance of VM
/// Might choose implementation depending on supplied gas.
pub fn create(&self, gas: &U256) -> Box<Vm> {
#[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) {
Box::new(super::interpreter::Interpreter::<usize>::new(self.evm_cache.clone()))
@@ -51,13 +68,23 @@ impl Factory {
}
}
fn can_fit_in_usize(gas: &U256) -> bool {
gas == &U256::from(gas.low_u64() as usize)
fn can_fit_in_usize(gas: U256) -> bool {
gas == U256::from(gas.low_u64() as usize)
}
}
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,
@@ -68,13 +95,30 @@ impl Default for Factory {
#[test]
fn test_create_vm() {
let _vm = Factory::default().create(&U256::zero());
let _vm = Factory::default().create(U256::zero());
}
/// 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);

View File

@@ -913,13 +913,8 @@ mod tests {
use rustc_hex::FromHex;
use vmtype::VMType;
use factory::Factory;
use vm::{Vm, ActionParams, ActionValue};
use vm::{ActionParams, ActionValue};
use vm::tests::{FakeExt, test_finalize};
use ethereum_types::U256;
fn interpreter(gas: &U256) -> Box<Vm> {
Factory::new(VMType::Interpreter, 1).create(gas)
}
#[test]
fn should_not_fail_on_tracing_mem() {
@@ -936,7 +931,7 @@ mod tests {
ext.tracing = true;
let gas_left = {
let mut vm = interpreter(&params.gas);
let mut vm = Factory::new(VMType::Interpreter, 1).create(params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
};
@@ -958,7 +953,7 @@ mod tests {
ext.tracing = true;
let err = {
let mut vm = interpreter(&params.gas);
let mut vm = Factory::new(VMType::Interpreter, 1).create(params.gas);
test_finalize(vm.exec(params, &mut ext)).err().unwrap()
};

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();
@@ -38,7 +38,7 @@ fn test_add(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
};
@@ -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();
@@ -58,7 +58,7 @@ fn test_sha3(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).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();
@@ -78,7 +78,7 @@ fn test_address(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).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();
@@ -100,7 +100,7 @@ fn test_origin(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).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();
@@ -122,7 +122,7 @@ fn test_sender(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).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
@@ -157,7 +157,7 @@ fn test_extcodecopy(factory: super::Factory) {
ext.codes.insert(sender, Arc::new(sender_code));
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
};
@@ -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();
@@ -177,7 +177,7 @@ fn test_log_empty(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).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
@@ -209,7 +209,7 @@ fn test_log_sender(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
};
@@ -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();
@@ -234,7 +234,7 @@ fn test_blockhash(factory: super::Factory) {
ext.blockhashes.insert(U256::zero(), blockhash.clone());
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).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();
@@ -256,7 +256,7 @@ fn test_calldataload(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).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();
@@ -277,7 +277,7 @@ fn test_author(factory: super::Factory) {
ext.info.author = author;
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).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();
@@ -297,7 +297,7 @@ fn test_timestamp(factory: super::Factory) {
ext.info.timestamp = timestamp;
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).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();
@@ -317,7 +317,7 @@ fn test_number(factory: super::Factory) {
ext.info.number = number;
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).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();
@@ -337,7 +337,7 @@ fn test_difficulty(factory: super::Factory) {
ext.info.difficulty = difficulty;
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).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();
@@ -357,7 +357,7 @@ fn test_gas_limit(factory: super::Factory) {
ext.info.gas_limit = gas_limit;
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).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();
@@ -375,7 +375,7 @@ fn test_mul(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).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();
@@ -393,7 +393,7 @@ fn test_sub(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).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();
@@ -411,7 +411,7 @@ fn test_div(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).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();
@@ -429,7 +429,7 @@ fn test_div_zero(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).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();
@@ -447,7 +447,7 @@ fn test_mod(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).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();
@@ -466,7 +466,7 @@ fn test_smod(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).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();
@@ -485,7 +485,7 @@ fn test_sdiv(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).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();
@@ -504,7 +504,7 @@ fn test_exp(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).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();
@@ -524,7 +524,7 @@ fn test_comparison(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).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();
@@ -545,7 +545,7 @@ fn test_signed_comparison(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).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();
@@ -566,7 +566,7 @@ fn test_bitops(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).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();
@@ -589,7 +589,7 @@ fn test_addmod_mulmod(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).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();
@@ -610,7 +610,7 @@ fn test_byte(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).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();
@@ -629,7 +629,7 @@ fn test_signextend(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
};
@@ -649,7 +649,7 @@ fn test_badinstruction_int() {
let mut ext = FakeExt::new();
let err = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap_err()
};
@@ -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();
@@ -669,7 +669,7 @@ fn test_pop(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).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();
@@ -689,7 +689,7 @@ fn test_extops(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).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();
@@ -712,7 +712,7 @@ fn test_jumps(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).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();
@@ -740,7 +740,7 @@ fn test_calls(factory: super::Factory) {
};
let gas_left = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).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();
@@ -779,7 +779,7 @@ fn test_create_in_staticcall(factory: super::Factory) {
ext.is_static = true;
let err = {
let mut vm = factory.create(&params.gas);
let mut vm = factory.create(params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap_err()
};

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,17 +11,19 @@ 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" }
ethcore-io = { path = "../../util/io" }
evm = { path = "../evm" }
hashdb = { path = "../../util/hashdb" }
heapsize = "0.4"
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 +36,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

@@ -60,6 +60,7 @@ extern crate ethcore_bytes as bytes;
extern crate ethcore_transaction as transaction;
extern crate ethereum_types;
extern crate ethcore;
extern crate evm;
extern crate hashdb;
extern crate heapsize;
extern crate futures;
@@ -75,15 +76,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,34 +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);
/// Max number of transactions in a single packet.
const MAX_TRANSACTIONS_TO_PROPAGATE: usize = 64;
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 {
@@ -115,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.
@@ -152,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
@@ -163,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
@@ -375,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 {
@@ -455,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)
}
}
@@ -465,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);
@@ -478,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
}
@@ -534,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)?;
@@ -545,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();
@@ -578,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);
@@ -607,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();
@@ -627,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();
@@ -651,7 +643,7 @@ impl LightProtocol {
fn propagate_transactions(&self, io: &IoContext) {
if self.capabilities.read().tx_relay { return }
let ready_transactions = self.provider.ready_transactions(MAX_TRANSACTIONS_TO_PROPAGATE);
let ready_transactions = self.provider.ready_transactions();
if ready_transactions.is_empty() { return }
trace!(target: "pip", "propagate transactions: {} ready", ready_transactions.len());
@@ -694,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;
}
@@ -717,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);
@@ -772,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);
@@ -800,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 => {
@@ -861,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(())
@@ -906,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;
@@ -974,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)?;
@@ -993,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)?;
@@ -1028,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();
@@ -1047,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()
@@ -1086,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.
@@ -173,8 +172,8 @@ impl Provider for TestProvider {
})
}
fn ready_transactions(&self, max_len: usize) -> Vec<PendingTransaction> {
self.0.client.ready_transactions(max_len)
fn ready_transactions(&self) -> Vec<PendingTransaction> {
self.0.client.ready_transactions()
}
}
@@ -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

@@ -18,7 +18,6 @@
//! The request service is implemented using Futures. Higher level request handlers
//! will take the raw data received here and extract meaningful results from it.
use std::cmp;
use std::collections::HashMap;
use std::marker::PhantomData;
use std::sync::Arc;
@@ -367,7 +366,7 @@ impl OnDemand {
.filter_map(|pending| {
// the peer we dispatch to is chosen randomly
let num_peers = peers.len();
let rng = rand::random::<usize>() % cmp::max(num_peers, 1);
let rng = rand::random::<usize>() % num_peers;
for (peer_id, peer) in peers.iter().chain(peers.iter()).skip(rng).take(num_peers) {
// TODO: see which requests can be answered by the cache?

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)
@@ -128,7 +125,7 @@ pub trait Provider: Send + Sync {
fn header_proof(&self, req: request::CompleteHeaderProofRequest) -> Option<request::HeaderProofResponse>;
/// Provide pending transactions.
fn ready_transactions(&self, max_len: usize) -> Vec<PendingTransaction>;
fn ready_transactions(&self) -> Vec<PendingTransaction>;
/// Provide a proof-of-execution for the given transaction proof request.
/// Returns a vector of all state items necessary to execute the transaction.
@@ -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)
@@ -283,11 +280,8 @@ impl<T: ProvingBlockChainClient + ?Sized> Provider for T {
.map(|(_, proof)| ::request::ExecutionResponse { items: proof })
}
fn ready_transactions(&self, max_len: usize) -> Vec<PendingTransaction> {
BlockChainClient::ready_transactions(self, max_len)
.into_iter()
.map(|tx| tx.pending().clone())
.collect()
fn ready_transactions(&self) -> Vec<PendingTransaction> {
BlockChainClient::ready_transactions(self)
}
fn epoch_signal(&self, req: request::CompleteSignalRequest) -> Option<request::SignalResponse> {
@@ -370,12 +364,9 @@ impl<L: AsLightClient + Send + Sync> Provider for LightProvider<L> {
None
}
fn ready_transactions(&self, max_len: usize) -> Vec<PendingTransaction> {
fn ready_transactions(&self) -> Vec<PendingTransaction> {
let chain_info = self.chain_info();
let mut transactions = self.txqueue.read()
.ready_transactions(chain_info.best_block_number, chain_info.best_block_timestamp);
transactions.truncate(max_len);
transactions
self.txqueue.read().ready_transactions(chain_info.best_block_number, chain_info.best_block_timestamp)
}
}

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,19 @@
[package]
name = "ethcore-migrations"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
ethcore-bytes = { path = "../../util/bytes" }
ethereum-types = "0.2"
keccak-hash = { path = "../../util/hash" }
kvdb = { path = "../../util/kvdb" }
kvdb-rocksdb = { path = "../../util/kvdb-rocksdb" }
log = "0.3"
macros = { path = "../../util/macros" }
migration = { path = "../../util/migration" }
rlp = { path = "../../util/rlp" }
patricia-trie = { path = "../../util/patricia_trie" }
journaldb = { path = "../../util/journaldb" }
ethcore-bloom-journal = { path = "../../util/bloom" }
ethcore = { path = ".." }

View File

@@ -1,4 +1,4 @@
// 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
@@ -14,8 +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/>.
extern crate parity_dapps_glue;
//! Blocks database migrations.
fn main() {
parity_dapps_glue::generate();
}
mod v8;
pub use self::v8::V8;

View File

@@ -14,10 +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/>.
use error::TransactionImportError;
//! This migration compresses the state db.
/// 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>;
use migration::{SimpleMigration, Progress};
use rlp::{Compressible, UntrustedRlp, RlpType};
/// Compressing migration.
#[derive(Default)]
pub struct V8(Progress);
impl SimpleMigration for V8 {
fn version(&self) -> u32 {
8
}
fn columns(&self) -> Option<u32> { None }
fn simple_migrate(&mut self, key: Vec<u8>, value: Vec<u8>) -> Option<(Vec<u8>, Vec<u8>)> {
self.0.tick();
Some((key,UntrustedRlp::new(&value).compress(RlpType::Blocks).into_vec()))
}
}

View File

@@ -1,4 +1,4 @@
// 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
@@ -14,8 +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/>.
#[cfg(feature = "with-syntex")]
include!(concat!(env!("OUT_DIR"), "/lib.rs"));
//! Extras database migrations.
#[cfg(not(feature = "with-syntex"))]
include!("lib.rs.in");
mod v6;
pub use self::v6::ToV6;

View File

@@ -0,0 +1,102 @@
// 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 migration::SimpleMigration;
/// This migration reduces the sizes of keys and moves `ExtrasIndex` byte from back to the front.
pub struct ToV6;
impl ToV6 {
fn migrate_old_key(&self, old_key: Vec<u8>, index: u8, len: usize) -> Vec<u8> {
let mut result = vec![];
result.reserve(len);
unsafe {
result.set_len(len);
}
result[0] = index;
let old_key_start = 33 - len;
result[1..].clone_from_slice(&old_key[old_key_start..32]);
result
}
}
impl SimpleMigration for ToV6 {
fn columns(&self) -> Option<u32> { None }
fn version(&self) -> u32 { 6 }
fn simple_migrate(&mut self, mut key: Vec<u8>, value: Vec<u8>) -> Option<(Vec<u8>, Vec<u8>)> {
//// at this version all extras keys are 33 bytes long.
if key.len() == 33 {
// block details key changes:
// - index is moved to the front
if key[32] == 0 {
return Some((self.migrate_old_key(key, 0, 33), value));
}
// block hash key changes:
// - key is shorter 33 -> 5 bytes
// - index is moved to the front
if key[32] == 1 {
return Some((self.migrate_old_key(key, 1, 5), value));
}
// transaction addresses changes:
// - index is moved to the front
if key[32] == 2 {
return Some((self.migrate_old_key(key, 2, 33), value));
}
// block log blooms are removed
if key[32] == 3 {
return None;
}
// blocks blooms key changes:
// - key is shorter 33 -> 6 bytes
// - index is moved to the front
// - index is changed 4 -> 3
if key[32] == 4 {
key.reverse();
// i have no idea why it was reversed
let reverse = key;
let result = vec![
// new extras index is 3
3,
// 9th (+ prefix) byte was the level. Now it's second.
reverse[9],
reverse[4],
reverse[3],
reverse[2],
reverse[1],
];
return Some((result, value));
}
// blocks receipts key changes:
// - index is moved to the front
// - index is changed 5 -> 4
if key[32] == 5 {
return Some((self.migrate_old_key(key, 4, 33), value));
}
}
Some((key, value))
}
}

View File

@@ -0,0 +1,62 @@
// 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/>.
//! Database migrations.
#[macro_use]
extern crate log;
#[macro_use]
extern crate macros;
extern crate migration;
extern crate rlp;
extern crate ethereum_types;
extern crate ethcore_bytes as bytes;
extern crate kvdb;
extern crate kvdb_rocksdb;
extern crate keccak_hash as hash;
extern crate journaldb;
extern crate ethcore_bloom_journal as bloom_journal;
extern crate ethcore;
extern crate patricia_trie as trie;
use migration::ChangeColumns;
pub mod state;
pub mod blocks;
pub mod extras;
mod v9;
pub use self::v9::ToV9;
pub use self::v9::Extract;
mod v10;
pub use self::v10::ToV10;
/// 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

@@ -14,14 +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/>.
extern crate futures;
extern crate ethabi;
extern crate keccak_hash;
//! State database migrations.
#[macro_use]
extern crate ethabi_derive;
#[macro_use]
extern crate ethabi_contract;
mod v7;
mod registrar;
pub use registrar::{Registrar, RegistrarClient, Synchronous, Asynchronous};
pub use self::v7::{ArchiveV7, OverlayRecentV7};

View File

@@ -0,0 +1,263 @@
// 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/>.
//! This migration migrates the state db to use an accountdb which ensures uniqueness
//! using an address' hash as opposed to the address itself.
use std::collections::HashMap;
use ethereum_types::{H256, Address};
use bytes::Bytes;
use kvdb_rocksdb::Database;
use migration::{Batch, Config, Error, ErrorKind, Migration, SimpleMigration, Progress};
use hash::keccak;
use std::sync::Arc;
use rlp::{decode, Rlp, RlpStream};
// attempt to migrate a key, value pair. None if migration not possible.
fn attempt_migrate(mut key_h: H256, val: &[u8]) -> Option<H256> {
let val_hash = keccak(val);
if key_h != val_hash {
// this is a key which has been xor'd with an address.
// recover the address.
let address = key_h ^ val_hash;
// check that the address is actually a 20-byte value.
// the leftmost 12 bytes should be zero.
if &address[0..12] != &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] {
return None;
}
let address_hash = keccak(Address::from(address));
// create the xor'd key in place.
key_h.copy_from_slice(&*val_hash);
assert_eq!(key_h, val_hash);
{
let last_src: &[u8] = &*address_hash;
let last_dst: &mut [u8] = &mut *key_h;
for (k, a) in last_dst[12..].iter_mut().zip(&last_src[12..]) {
*k ^= *a;
}
}
Some(key_h)
} else {
None
}
}
/// Version for `ArchiveDB`.
#[derive(Default)]
pub struct ArchiveV7(Progress);
impl SimpleMigration for ArchiveV7 {
fn columns(&self) -> Option<u32> { None }
fn version(&self) -> u32 { 7 }
fn simple_migrate(&mut self, key: Vec<u8>, value: Vec<u8>) -> Option<(Vec<u8>, Vec<u8>)> {
self.0.tick();
if key.len() != 32 {
// metadata key, ignore.
return Some((key, value));
}
let key_h = H256::from_slice(&key[..]);
if let Some(new_key) = attempt_migrate(key_h, &value[..]) {
Some((new_key[..].to_owned(), value))
} else {
Some((key, value))
}
}
}
// magic numbers and constants for overlay-recent at v6.
// re-written here because it may change in the journaldb module.
const V7_LATEST_ERA_KEY: &'static [u8] = &[ b'l', b'a', b's', b't', 0, 0, 0, 0, 0, 0, 0, 0 ];
const V7_VERSION_KEY: &'static [u8] = &[ b'j', b'v', b'e', b'r', 0, 0, 0, 0, 0, 0, 0, 0 ];
const DB_VERSION: u32 = 0x203;
const PADDING : [u8; 10] = [0u8; 10];
/// Version for `OverlayRecent` database.
/// more involved than the archive version because of journaling.
#[derive(Default)]
pub struct OverlayRecentV7 {
migrated_keys: HashMap<H256, H256>,
}
impl OverlayRecentV7 {
// walk all journal entries in the database backwards.
// find migrations for any possible inserted keys.
fn walk_journal(&mut self, source: Arc<Database>) -> Result<(), Error> {
if let Some(val) = source.get(None, V7_LATEST_ERA_KEY)? {
let mut era = decode::<u64>(&val);
loop {
let mut index: usize = 0;
loop {
let entry_key = {
let mut r = RlpStream::new_list(3);
r.append(&era).append(&index).append(&&PADDING[..]);
r.out()
};
if let Some(journal_raw) = source.get(None, &entry_key)? {
let rlp = Rlp::new(&journal_raw);
// migrate all inserted keys.
for r in rlp.at(1).iter() {
let key: H256 = r.val_at(0);
let v: Bytes = r.val_at(1);
if self.migrated_keys.get(&key).is_none() {
if let Some(new_key) = attempt_migrate(key, &v) {
self.migrated_keys.insert(key, new_key);
}
}
}
index += 1;
} else {
break;
}
}
if index == 0 || era == 0 {
break;
}
era -= 1;
}
}
Ok(())
}
// walk all journal entries in the database backwards.
// replace all possible inserted/deleted keys with their migrated counterparts
// and commit the altered entries.
fn migrate_journal(&self, source: Arc<Database>, mut batch: Batch, dest: &mut Database) -> Result<(), Error> {
if let Some(val) = source.get(None, V7_LATEST_ERA_KEY)? {
batch.insert(V7_LATEST_ERA_KEY.into(), val.clone().into_vec(), dest)?;
let mut era = decode::<u64>(&val);
loop {
let mut index: usize = 0;
loop {
let entry_key = {
let mut r = RlpStream::new_list(3);
r.append(&era).append(&index).append(&&PADDING[..]);
r.out()
};
if let Some(journal_raw) = source.get(None, &entry_key)? {
let rlp = Rlp::new(&journal_raw);
let id: H256 = rlp.val_at(0);
let mut inserted_keys: Vec<(H256, Bytes)> = Vec::new();
// migrate all inserted keys.
for r in rlp.at(1).iter() {
let mut key: H256 = r.val_at(0);
let v: Bytes = r.val_at(1);
if let Some(new_key) = self.migrated_keys.get(&key) {
key = *new_key;
}
inserted_keys.push((key, v));
}
// migrate all deleted keys.
let mut deleted_keys: Vec<H256> = rlp.list_at(2);
for old_key in &mut deleted_keys {
if let Some(new) = self.migrated_keys.get(&*old_key) {
*old_key = new.clone();
}
}
// rebuild the journal entry rlp.
let mut stream = RlpStream::new_list(3);
stream.append(&id);
stream.begin_list(inserted_keys.len());
for (k, v) in inserted_keys {
stream.begin_list(2).append(&k).append(&v);
}
stream.append_list(&deleted_keys);
// and insert it into the new database.
batch.insert(entry_key, stream.out(), dest)?;
index += 1;
} else {
break;
}
}
if index == 0 || era == 0 {
break;
}
era -= 1;
}
}
batch.commit(dest)
}
}
impl Migration for OverlayRecentV7 {
fn columns(&self) -> Option<u32> { None }
fn version(&self) -> u32 { 7 }
// walk all records in the database, attempting to migrate any possible and
// keeping records of those that we do. then migrate the journal using
// this information.
fn migrate(&mut self, source: Arc<Database>, config: &Config, dest: &mut Database, col: Option<u32>) -> Result<(), Error> {
let mut batch = Batch::new(config, col);
// check version metadata.
match source.get(None, V7_VERSION_KEY)? {
Some(ref version) if decode::<u32>(&*version) == DB_VERSION => {}
_ => return Err(ErrorKind::MigrationImpossible.into()), // missing or wrong version
}
let mut count = 0;
for (key, value) in source.iter(None).into_iter().flat_map(|inner| inner) {
count += 1;
if count == 100_000 {
count = 0;
flush!(".");
}
let mut key = key.into_vec();
if key.len() == 32 {
let key_h = H256::from_slice(&key[..]);
if let Some(new_key) = attempt_migrate(key_h.clone(), &value) {
self.migrated_keys.insert(key_h, new_key);
key.copy_from_slice(&new_key[..]);
}
}
batch.insert(key, value.into_vec(), dest)?;
}
self.walk_journal(source.clone())?;
self.migrate_journal(source, batch, dest)
}
}

View File

@@ -0,0 +1,119 @@
// 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/>.
//! Bloom upgrade
use std::sync::Arc;
use ethcore::db::{COL_EXTRA, COL_HEADERS, COL_STATE};
use ethcore::state_db::{ACCOUNT_BLOOM_SPACE, DEFAULT_ACCOUNT_PRESET, StateDB};
use trie::TrieDB;
use ethcore::views::HeaderView;
use bloom_journal::Bloom;
use migration::{Error, Migration, Progress, Batch, Config, ErrorKind};
use journaldb;
use ethereum_types::H256;
use trie::Trie;
use kvdb::{DBTransaction, ResultExt};
use kvdb_rocksdb::Database;
/// Account bloom upgrade routine. If bloom already present, does nothing.
/// If database empty (no best block), does nothing.
/// Can be called on upgraded database with no issues (will do nothing).
pub fn generate_bloom(source: Arc<Database>, dest: &mut Database) -> Result<(), Error> {
trace!(target: "migration", "Account bloom upgrade started");
let best_block_hash = match source.get(COL_EXTRA, b"best")? {
// no migration needed
None => {
trace!(target: "migration", "No best block hash, skipping");
return Ok(());
},
Some(hash) => hash,
};
let best_block_header = match source.get(COL_HEADERS, &best_block_hash)? {
// no best block, nothing to do
None => {
trace!(target: "migration", "No best block header, skipping");
return Ok(())
},
Some(x) => x,
};
let state_root = HeaderView::new(&best_block_header).state_root();
trace!("Adding accounts bloom (one-time upgrade)");
let bloom_journal = {
let mut bloom = Bloom::new(ACCOUNT_BLOOM_SPACE, DEFAULT_ACCOUNT_PRESET);
// no difference what algorithm is passed, since there will be no writes
let state_db = journaldb::new(
source.clone(),
journaldb::Algorithm::OverlayRecent,
COL_STATE);
let account_trie = TrieDB::new(state_db.as_hashdb(), &state_root).chain_err(|| "Cannot open trie")?;
for item in account_trie.iter().map_err(|_| ErrorKind::MigrationImpossible)? {
let (ref account_key, _) = item.map_err(|_| ErrorKind::MigrationImpossible)?;
let account_key_hash = H256::from_slice(account_key);
bloom.set(&*account_key_hash);
}
bloom.drain_journal()
};
trace!(target: "migration", "Generated {} bloom updates", bloom_journal.entries.len());
let mut batch = DBTransaction::new();
StateDB::commit_bloom(&mut batch, bloom_journal).chain_err(|| "Failed to commit bloom")?;
dest.write(batch)?;
trace!(target: "migration", "Finished bloom update");
Ok(())
}
/// Account bloom migration.
#[derive(Default)]
pub struct ToV10 {
progress: Progress,
}
impl ToV10 {
/// New v10 migration
pub fn new() -> ToV10 { ToV10 { progress: Progress::default() } }
}
impl Migration for ToV10 {
fn version(&self) -> u32 {
10
}
fn pre_columns(&self) -> Option<u32> { Some(5) }
fn columns(&self) -> Option<u32> { Some(6) }
fn migrate(&mut self, source: Arc<Database>, config: &Config, dest: &mut Database, col: Option<u32>) -> Result<(), Error> {
let mut batch = Batch::new(config, col);
for (key, value) in source.iter(col).into_iter().flat_map(|inner| inner) {
self.progress.tick();
batch.insert(key.into_vec(), value.into_vec(), dest)?;
}
batch.commit(dest)?;
if col == COL_STATE {
generate_bloom(source, dest)?;
}
Ok(())
}
}

View File

@@ -0,0 +1,82 @@
// 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/>.
//! This migration consolidates all databases into single one using Column Families.
use rlp::{Rlp, RlpStream};
use kvdb_rocksdb::Database;
use migration::{Batch, Config, Error, Migration, Progress};
use std::sync::Arc;
/// Which part of block to preserve
pub enum Extract {
/// Extract block header RLP.
Header,
/// Extract block body RLP.
Body,
/// Don't change the value.
All,
}
/// Consolidation of extras/block/state databases into single one.
pub struct ToV9 {
progress: Progress,
column: Option<u32>,
extract: Extract,
}
impl ToV9 {
/// Creates new V9 migration and assigns all `(key,value)` pairs from `source` DB to given Column Family
pub fn new(column: Option<u32>, extract: Extract) -> Self {
ToV9 {
progress: Progress::default(),
column: column,
extract: extract,
}
}
}
impl Migration for ToV9 {
fn columns(&self) -> Option<u32> { Some(5) }
fn version(&self) -> u32 { 9 }
fn migrate(&mut self, source: Arc<Database>, config: &Config, dest: &mut Database, col: Option<u32>) -> Result<(), Error> {
let mut batch = Batch::new(config, self.column);
for (key, value) in source.iter(col).into_iter().flat_map(|inner| inner) {
self.progress.tick();
match self.extract {
Extract::Header => {
batch.insert(key.into_vec(), Rlp::new(&value).at(0).as_raw().to_vec(), dest)?
},
Extract::Body => {
let mut body = RlpStream::new_list(2);
let block_rlp = Rlp::new(&value);
body.append_raw(block_rlp.at(1).as_raw(), 1);
body.append_raw(block_rlp.at(2).as_raw(), 1);
batch.insert(key.into_vec(), body.out(), dest)?
},
Extract::All => {
batch.insert(key.into_vec(), value.into_vec(), dest)?
}
}
}
batch.commit(dest)
}
}

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

@@ -26,7 +26,6 @@
"minGasLimit": "0x1388",
"networkID" : "0x1",
"maxCodeSize": 24576,
"maxCodeSizeTransition": "0x0",
"eip98Transition": "0xffffffffffffffff",
"eip140Transition": "0x0",
"eip211Transition": "0x0",

File diff suppressed because it is too large Load Diff

View File

@@ -26,7 +26,6 @@
"minGasLimit": "0x1388",
"networkID" : "0x1",
"maxCodeSize": 24576,
"maxCodeSizeTransition": "0x0",
"eip98Transition": "0xffffffffffffffff",
"eip140Transition": "0x0",
"eip210Transition": "0x0",

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

@@ -25,8 +25,7 @@
"eip98Transition": "0x7fffffffffffffff",
"eip86Transition": "0x7fffffffffffffff",
"eip155Transition": "0x7fffffffffffffff",
"maxCodeSize": 24576,
"maxCodeSizeTransition": "0x7fffffffffffffff"
"maxCodeSize": 24576
},
"genesis": {
"seal": {

View File

@@ -25,8 +25,7 @@
"eip98Transition": "0x7fffffffffffffff",
"eip86Transition": "0x7fffffffffffffff",
"eip155Transition": "0x7fffffffffffffff",
"maxCodeSize": 24576,
"maxCodeSizeTransition": "0x0"
"maxCodeSize": 24576
},
"genesis": {
"seal": {

View File

@@ -13,9 +13,9 @@
"eip150Transition": "0x0",
"eip160Transition": "0x0",
"ecip1017EraRounds": 10000000,
"eip161abcTransition": "0x7fffffffffffffff",
"eip161dTransition": "0x7fffffffffffffff",
"eip100bTransition": 2000000
"eip161dTransition": "0x7fffffffffffffff"
}
}
},
@@ -29,12 +29,7 @@
"chainID": "0x40",
"eip155Transition": "0x0",
"eip98Transition": "0x7fffffffffffff",
"eip86Transition": "0x7fffffffffffff",
"wasmActivationTransition": 2000000,
"eip140Transition": 2000000,
"eip211Transition": 2000000,
"eip214Transition": 2000000,
"eip658Transition": 2000000
"eip86Transition": "0x7fffffffffffff"
},
"genesis": {
"seal": {
@@ -51,24 +46,27 @@
"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": {
"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 } } } },
"0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": 2000000, "pricing": { "modexp": { "divisor": 20 } } } },
"0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": 2000000, "pricing": { "linear": { "base": 500, "word": 0 } } } },
"0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": 2000000, "pricing": { "linear": { "base": 40000, "word": 0 } } } },
"0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": 2000000, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }
"0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }
}
}

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