Merge branch 'master' into secretstore_kovan

This commit is contained in:
Svyatoslav Nikolsky 2017-12-27 11:44:28 +03:00
commit c0e7abcc81
203 changed files with 6090 additions and 1869 deletions

84
.github/CODE_OF_CONDUCT.md vendored Normal file
View File

@ -0,0 +1,84 @@
# Code of Conduct
## 1. Purpose
A primary goal of Parity is to be inclusive to the largest number of contributors, with the most varied and diverse backgrounds possible. As such, we are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, sexual orientation, ability, ethnicity, socioeconomic status, and religion (or lack thereof).
This code of conduct outlines our expectations for all those who participate in our community, as well as the consequences for unacceptable behavior.
We invite all those who participate in Parity to help us create safe and positive experiences for everyone.
## 2. Open Source Citizenship
A supplemental goal of this Code of Conduct is to increase open source citizenship by encouraging participants to recognize and strengthen the relationships between our actions and their effects on our community.
Communities mirror the societies in which they exist and positive action is essential to counteract the many forms of inequality and abuses of power that exist in society.
If you see someone who is making an extra effort to ensure our community is welcoming, friendly, and encourages all participants to contribute to the fullest extent, we want to know.
## 3. Expected Behavior
The following behaviors are expected and requested of all community members:
* Participate in an authentic and active way. In doing so, you contribute to the health and longevity of this community.
* Exercise consideration and respect in your speech and actions.
* Attempt collaboration before conflict.
* Refrain from demeaning, discriminatory, or harassing behavior and speech.
* Be mindful of your surroundings and of your fellow participants. Alert community leaders if you notice a dangerous situation, someone in distress, or violations of this Code of Conduct, even if they seem inconsequential.
* Remember that community event venues may be shared with members of the public; please be respectful to all patrons of these locations.
## 4. Unacceptable Behavior
The following behaviors are considered harassment and are unacceptable within our community:
* Violence, threats of violence or violent language directed against another person.
* Sexist, racist, homophobic, transphobic, ableist or otherwise discriminatory jokes and language.
* Posting or displaying sexually explicit or violent material.
* Posting or threatening to post other peoples personally identifying information ("doxing").
* Personal insults, particularly those related to gender, sexual orientation, race, religion, or disability.
* Inappropriate photography or recording.
* Inappropriate physical contact. You should have someones consent before touching them.
* Unwelcome sexual attention. This includes, sexualized comments or jokes; inappropriate touching, groping, and unwelcomed sexual advances.
* Deliberate intimidation, stalking or following (online or in person).
* Advocating for, or encouraging, any of the above behavior.
* Sustained disruption of community events, including talks and presentations.
## 5. Consequences of Unacceptable Behavior
Unacceptable behavior from any community member, including sponsors and those with decision-making authority, will not be tolerated.
Anyone asked to stop unacceptable behavior is expected to comply immediately.
If a community member engages in unacceptable behavior, the community organizers may take any action they deem appropriate, up to and including a temporary ban or permanent expulsion from the community without warning (and without refund in the case of a paid event).
## 6. Reporting Guidelines
If you are subject to or witness unacceptable behavior, or have any other concerns, please notify a community organizer as soon as possible. community@parity.io.
Link to reporting guidelines: [CONTRIBUTING.md](CONTRIBUTING.md)
Link to security policy: [SECURITY.md](../SECURITY.md)
Additionally, community organizers are available to help community members engage with local law enforcement or to otherwise help those experiencing unacceptable behavior feel safe. In the context of in-person events, organizers will also provide escorts as desired by the person experiencing distress.
## 7. Addressing Grievances
If you feel you have been falsely or unfairly accused of violating this Code of Conduct, you should notify Parity Technologies with a concise description of your grievance. Your grievance will be handled in accordance with our existing governing policies.
## 8. Scope
We expect all community participants (contributors, paid or otherwise; sponsors; and other guests) to abide by this Code of Conduct in all community venuesonline and in-personas well as in all one-on-one communications pertaining to community business.
This code of conduct and its related procedures also applies to unacceptable behavior occurring outside the scope of community activities when such behavior has the potential to adversely affect the safety and well-being of community members.
## 9. Contact info
You can contact Parity via Email: community@parity.io
## 10. License and attribution
This Code of Conduct is distributed under a [Creative Commons Attribution-ShareAlike license](http://creativecommons.org/licenses/by-sa/3.0/).
Portions of text derived from the [Django Code of Conduct](https://www.djangoproject.com/conduct/) and the [Geek Feminism Anti-Harassment Policy](http://geekfeminism.wikia.com/wiki/Conference_anti-harassment/Policy).
Retrieved on November 22, 2016 from [http://citizencodeofconduct.org/](http://citizencodeofconduct.org/)

33
.github/CONTRIBUTING.md vendored Normal file
View File

@ -0,0 +1,33 @@
# Contributing Guidelines
## Do you have a question?
Check out our [Basic Usage](https://github.com/paritytech/parity/wiki/Basic-Usage), [Configuration](https://github.com/paritytech/parity/wiki/Configuring-Parity), and [FAQ](https://github.com/paritytech/parity/wiki/FAQ) articles on our [wiki](https://github.com/paritytech/parity/wiki)!
See also frequently asked questions [tagged with `parity`](https://ethereum.stackexchange.com/questions/tagged/parity?sort=votes&pageSize=50) on Stack Exchange.
## Report bugs!
Do **not** open an issue on Github if you think your discovered bug could be a **security-relevant vulnerability**. Please, read our [security policy](../SECURITY.md) instead.
Otherwise, just create a [new issue](https://github.com/paritytech/parity/issues/new) in our repository and state:
- What's your Parity version?
- What's your operating system and version?
- How did you install parity?
- Is your node fully synchronized?
- Did you try turning it off and on again?
Also, try to include **steps to reproduce** the issue and expand on the **actual versus expected behavior**.
## Contribute!
If you would like to contribute to Parity, please **fork it**, fix bugs or implement features, and [propose a pull request](https://github.com/paritytech/parity/compare).
Please, refer to the [Coding Guide](https://github.com/paritytech/parity/wiki/Coding-guide) in our wiki for more details about hacking on Parity.
## License.
By contributing to Parity, you agree that your contributions will be licensed under the [GPLv3 License](../LICENSE).
Each contributor has to sign our Contributor License Agreement. The purpose of the CLA is to ensure that the guardian of a project's outputs has the necessary ownership or grants of rights over all contributions to allow them to distribute under the chosen license. You can read and sign our full Contributor License Agreement at [cla.parity.io](https://cla.parity.io) before submitting a pull request.

View File

@ -1,3 +1,48 @@
## Parity [v1.8.4](https://github.com/paritytech/parity/releases/tag/v1.8.4) (2017-12-12)
Parity 1.8.4 applies fixes for Proof-of-Authority networks and schedules the Kovan-Byzantium hard-fork.
- The Kovan testnet will fork on block `5067000` at `Thu Dec 14 2017 05:40:03 UTC`.
- This enables Byzantium features on Kovan.
- This disables uncles on Kovan for stability reasons.
- Proof-of-Authority networks are advised to set `maximumUncleCount` to 0 in a future `maximumUncleCountTransition` for stability reasons.
- See the [Kovan chain spec](https://github.com/paritytech/parity/blob/master/ethcore/res/ethereum/kovan.json) for an example.
- New PoA networks created with Parity will have this feature enabled by default.
Furthermore, this release includes the ECIP-1039 Monetary policy rounding specification for Ethereum Classic, reduces the maximum Ethash-block timestamp drift to 15 seconds, and fixes various bugs for WASM and the RPC APIs.
The full list of included changes:
- Beta Backports and HF block update ([#7244](https://github.com/paritytech/parity/pull/7244))
- Reduce max block timestamp drift to 15 seconds ([#7240](https://github.com/paritytech/parity/pull/7240))
- Add test for block timestamp validation within allowed drift
- Update kovan HF block number.
- Beta Kovan HF ([#7234](https://github.com/paritytech/parity/pull/7234))
- Kovan HF.
- Bump version.
- Fix aura difficulty race ([#7198](https://github.com/paritytech/parity/pull/7198))
- Fix test key
- Extract out score calculation
- Fix build
- Update kovan HF block number.
- Add missing byzantium builtins.
- Bump installers versions.
- Increase allowed time drift to 10s. ([#7238](https://github.com/paritytech/parity/pull/7238))
- Beta Backports ([#7197](https://github.com/paritytech/parity/pull/7197))
- Maximum uncle count transition ([#7196](https://github.com/paritytech/parity/pull/7196))
- Enable delayed maximum_uncle_count activation.
- Fix tests.
- Defer kovan HF.
- Disable uncles by default ([#7006](https://github.com/paritytech/parity/pull/7006))
- Escape inifinite loop in estimte_gas ([#7075](https://github.com/paritytech/parity/pull/7075))
- ECIP-1039: Monetary policy rounding specification ([#7067](https://github.com/paritytech/parity/pull/7067))
- WASM Remove blockhash error ([#7121](https://github.com/paritytech/parity/pull/7121))
- Remove blockhash error
- Update tests.
- WASM storage_read and storage_write don't return anything ([#7110](https://github.com/paritytech/parity/pull/7110))
- 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))
## Parity [v1.8.3](https://github.com/paritytech/parity/releases/tag/v1.8.3) (2017-11-15)
Parity 1.8.3 contains several bug-fixes and removes the ability to deploy built-in multi-signature wallets.

138
Cargo.lock generated
View File

@ -244,28 +244,6 @@ dependencies = [
"vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "clippy"
version = "0.0.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"clippy_lints 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "clippy_lints"
version = "0.0.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
"semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "coco"
version = "0.1.1"
@ -480,7 +458,6 @@ dependencies = [
"bloomchain 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bn 0.4.4 (git+https://github.com/paritytech/bn)",
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"common-types 0.1.0",
"crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
"ethash 1.9.0",
@ -554,6 +531,19 @@ dependencies = [
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ethcore-bigint"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
"plain_hasher 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ethcore-bloom-journal"
version = "0.1.0"
@ -641,7 +631,6 @@ version = "1.9.0"
dependencies = [
"ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-bigint 0.2.1",
"ethcore-bytes 0.1.0",
@ -727,32 +716,14 @@ dependencies = [
name = "ethcore-util"
version = "1.9.0"
dependencies = [
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)",
"ethcore-bigint 0.2.1",
"ethcore-bytes 0.1.0",
"ethcore-logger 1.9.0",
"hashdb 0.1.1",
"heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"journaldb 0.1.0",
"keccak-hash 0.1.0",
"kvdb 0.1.0",
"kvdb-memorydb 0.1.0",
"libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"memorydb 0.1.1",
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"patricia-trie 0.1.0",
"rlp 0.2.1",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"triehash 0.1.0",
"util-error 0.1.0",
"vergen 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -771,7 +742,6 @@ dependencies = [
name = "ethjson"
version = "0.1.0"
dependencies = [
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-bigint 0.2.1",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
@ -853,7 +823,6 @@ dependencies = [
name = "ethsync"
version = "1.9.0"
dependencies = [
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore 1.9.0",
"ethcore-bigint 0.2.1",
@ -1743,11 +1712,6 @@ dependencies = [
"odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "nom"
version = "1.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ntp"
version = "0.3.1"
@ -1916,7 +1880,6 @@ dependencies = [
"ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"app_dirs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.26.2 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"ctrlc 1.1.1 (git+https://github.com/paritytech/rust-ctrlc.git)",
"daemonize 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1959,6 +1922,7 @@ dependencies = [
"parity-rpc 1.9.0",
"parity-rpc-client 1.4.0",
"parity-updater 1.9.0",
"parity-version 0.1.0",
"parity-whisper 0.1.0",
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"path 0.1.0",
@ -1984,7 +1948,6 @@ name = "parity-dapps"
version = "1.9.0"
dependencies = [
"base32 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-bigint 0.2.1",
"ethcore-bytes 0.1.0",
@ -2005,6 +1968,7 @@ dependencies = [
"parity-hash-fetch 1.9.0",
"parity-reactor 0.1.0",
"parity-ui 1.9.0",
"parity-version 0.1.0",
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2020,7 +1984,6 @@ name = "parity-dapps-glue"
version = "1.9.1"
dependencies = [
"aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"mime_guess 2.0.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)",
"quasi 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2118,7 +2081,6 @@ version = "1.9.0"
dependencies = [
"ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cid 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"ethash 1.9.0",
"ethcore 1.9.0",
"ethcore-bigint 0.2.1",
@ -2154,6 +2116,7 @@ dependencies = [
"order-stat 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-reactor 0.1.0",
"parity-updater 1.9.0",
"parity-version 0.1.0",
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2234,7 +2197,7 @@ dependencies = [
[[package]]
name = "parity-ui-old-precompiled"
version = "1.9.0"
source = "git+https://github.com/js-dist-paritytech/parity-master-1-9-v1.git#3c4b36c8f9b182242c1355289dc448eac95c19c5"
source = "git+https://github.com/js-dist-paritytech/parity-master-1-9-v1.git#d95164e94df10cb2bbcaa5dad36d6b61b760c3e1"
dependencies = [
"parity-dapps-glue 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -2242,7 +2205,7 @@ dependencies = [
[[package]]
name = "parity-ui-precompiled"
version = "1.9.0"
source = "git+https://github.com/js-dist-paritytech/parity-master-1-9-shell.git#6dad0d219f9ad72f948f5f4138df3d6cf987b655"
source = "git+https://github.com/js-dist-paritytech/parity-master-1-9-shell.git#3bfd9abfca2ccadeb60aa6610ea0fbb9a8b74ac5"
dependencies = [
"parity-dapps-glue 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -2261,12 +2224,24 @@ dependencies = [
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-hash-fetch 1.9.0",
"parity-reactor 0.1.0",
"parity-version 0.1.0",
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"path 0.1.0",
"semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "parity-version"
version = "0.1.0"
dependencies = [
"ethcore-bytes 0.1.0",
"rlp 0.2.1",
"rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"vergen 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "parity-wasm"
version = "0.15.3"
@ -2410,6 +2385,14 @@ dependencies = [
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "plain_hasher"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "podio"
version = "0.1.5"
@ -2538,11 +2521,6 @@ name = "quick-error"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "quine-mc_cluskey"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "quote"
version = "0.3.15"
@ -2603,11 +2581,6 @@ dependencies = [
"utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex-syntax"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "regex-syntax"
version = "0.4.1"
@ -2836,14 +2809,6 @@ name = "semver"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "semver"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "semver"
version = "0.6.0"
@ -3256,14 +3221,6 @@ dependencies = [
"tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "toml"
version = "0.1.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "toml"
version = "0.4.5"
@ -3277,6 +3234,16 @@ name = "traitobject"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "transaction-pool"
version = "1.9.0"
dependencies = [
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "transient-hashmap"
version = "0.4.0"
@ -3585,8 +3552,6 @@ dependencies = [
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
"checksum cid 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "34aa7da06f10541fbca6850719cdaa8fa03060a5d2fb33840f149cf8133a00c7"
"checksum clap 2.26.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3451e409013178663435d6f15fdb212f14ee4424a3d74f979d081d0a66b6f1f2"
"checksum clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "5b4fabf979ddf6419a313c1c0ada4a5b95cfd2049c56e8418d622d27b4b6ff32"
"checksum clippy_lints 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "ce96ec05bfe018a0d5d43da115e54850ea2217981ff0f2e462780ab9d594651a"
"checksum coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c06169f5beb7e31c7c67ebf5540b8b472d23e3eade3b2ec7d1f5b504a85f91bd"
"checksum conv 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "78ff10625fd0ac447827aa30ea8b861fead473bb60aeb73af6c1c58caf0d1299"
"checksum cookie 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d53b80dde876f47f03cda35303e368a79b91c70b0d65ecba5fd5280944a08591"
@ -3609,6 +3574,7 @@ dependencies = [
"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
"checksum eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)" = "<none>"
"checksum ethabi 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c819a3adef0413a2519cbd9a19a35dd1c20c7a0110705beaba8aa4aa87eda95f"
"checksum ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcb5af77e74a8f70e9c3337e069c37bc82178ef1b459c02091f73c4ad5281eb5"
"checksum fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1ee15a7050e5580b3712877157068ea713b245b080ff302ae2ca973cfcd9baa"
"checksum flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "e6234dd4468ae5d1e2dbb06fe2b058696fdc50a339c68a393aefbf00bc81e423"
"checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344"
@ -3679,7 +3645,6 @@ dependencies = [
"checksum native-tls 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04b781c9134a954c84f0594b9ab3f5606abc516030388e8511887ef4c204a1e5"
"checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09"
"checksum nodrop 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "52cd74cd09beba596430cc6e3091b74007169a56246e1262f0ba451ea95117b2"
"checksum nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce"
"checksum ntp 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "143149743832c6543b60a8ef2a26cd9122dfecec2b767158e852a7beecf6d7a0"
"checksum num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "a311b77ebdc5dd4cf6449d81e4135d9f0e3b153839ac90e648a8ef538f923525"
"checksum num-bigint 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "8fd0f8dbb4c0960998958a796281d88c16fbe68d87b1baa6f31e2979e81fd0bd"
@ -3711,6 +3676,7 @@ dependencies = [
"checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03"
"checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2"
"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
"checksum plain_hasher 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83ae80873992f511142c07d0ec6c44de5636628fdb7e204abd655932ea79d995"
"checksum podio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e5422a1ee1bc57cc47ae717b0137314258138f38fd5f3cea083f43a9725383a0"
"checksum pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2412f3332a07c7a2a50168988dcc184f32180a9758ad470390e5f55e089f6b6e"
"checksum primal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0e31b86efadeaeb1235452171a66689682783149a6249ff334a2c5d8218d00a4"
@ -3724,7 +3690,6 @@ dependencies = [
"checksum quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9e25fa23c044c1803f43ca59c98dac608976dd04ce799411edd58ece776d4"
"checksum quasi_macros 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29cec87bc2816766d7e4168302d505dd06b0a825aed41b00633d296e922e02dd"
"checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4"
"checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45"
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
"checksum rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "eb250fd207a4729c976794d03db689c9be1d634ab5a1c9da9492a13d8fecbcdf"
"checksum rayon 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a77c51c07654ddd93f6cb543c7a849863b03abc7e82591afda6dc8ad4ac3ac4a"
@ -3732,7 +3697,6 @@ dependencies = [
"checksum rayon-core 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7febc28567082c345f10cddc3612c6ea020fc3297a1977d472cf9fdb73e6e493"
"checksum redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "8dde11f18c108289bef24469638a04dce49da56084f2d50618b226e47eb04509"
"checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b"
"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957"
"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
"checksum reqwest 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5866613d84e2a39c0479a960bf2d0eff1fbfc934f02cd42b5c08c1e1efc5b1fd"
"checksum ring 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)" = "24293de46bac74c9b9c05b40ff8496bbc8b9ae242a9b89f754e1154a43bc7c4c"
@ -3755,7 +3719,6 @@ dependencies = [
"checksum security-framework 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "dfa44ee9c54ce5eecc9de7d5acbad112ee58755239381f687e564004ba4a2332"
"checksum security-framework-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "5421621e836278a0b139268f36eee0dc7e389b784dc3f79d8f11aabadf41bead"
"checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac"
"checksum semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2d5b7638a1f03815d94e88cb3b3c08e87f0db4d683ef499d1836aaf70a45623f"
"checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537"
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
"checksum serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "6a7046c9d4c6c522d10b2d098f9bebe2bef227e0e74044d8c1bfcf6b476af799"
@ -3803,7 +3766,6 @@ dependencies = [
"checksum tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6131e780037787ff1b3f8aad9da83bca02438b72277850dd6ad0d455e0e20efc"
"checksum tokio-tls 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d88e411cac1c87e405e4090be004493c5d8072a370661033b1a64ea205ec2e13"
"checksum tokio-uds 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6116c71be48f8f1656551fd16458247fdd6c03201d7893ad81189055fcde03e8"
"checksum toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "0590d72182e50e879c4da3b11c6488dae18fccb1ae0c7a3eda18e16795844796"
"checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e"
"checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079"
"checksum transient-hashmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "715254c8f0811be1a79ad3ea5e6fa3c8eddec2b03d7f5ba78cf093e56d79c24f"

View File

@ -55,6 +55,7 @@ parity-reactor = { path = "util/reactor" }
parity-rpc = { path = "rpc" }
parity-rpc-client = { path = "rpc_client" }
parity-updater = { path = "updater" }
parity-version = { path = "util/version" }
parity-whisper = { path = "whisper" }
path = { path = "util/path" }
panic_hook = { path = "panic_hook" }
@ -65,7 +66,6 @@ kvdb-rocksdb = { path = "util/kvdb-rocksdb" }
journaldb = { path = "util/journaldb" }
parity-dapps = { path = "dapps", optional = true }
clippy = { version = "0.0.103", optional = true}
ethcore-secretstore = { path = "secret_store", optional = true }
[build-dependencies]
@ -94,13 +94,11 @@ ui-precompiled = [
ui-enabled = ["dapps"]
dapps = ["parity-dapps"]
jit = ["ethcore/jit"]
dev = ["clippy", "ethcore/dev", "ethcore-util/dev", "ethsync/dev", "parity-rpc/dev", "parity-dapps/dev"]
json-tests = ["ethcore/json-tests"]
test-heavy = ["ethcore/test-heavy"]
evm-debug = ["ethcore/evm-debug"]
evm-debug-tests = ["ethcore/evm-debug-tests"]
slow-blocks = ["ethcore/slow-blocks"]
final = ["ethcore-util/final"]
secretstore = ["ethcore-secretstore"]
[[bin]]
@ -116,4 +114,13 @@ lto = false
panic = "abort"
[workspace]
members = ["ethstore/cli", "ethkey/cli", "evmbin", "whisper", "chainspec", "dapps/js-glue", "ethcore/wasm/run"]
members = [
"chainspec",
"dapps/js-glue",
"ethcore/wasm/run",
"ethkey/cli",
"ethstore/cli",
"evmbin",
"transaction-pool",
"whisper",
]

View File

@ -94,12 +94,25 @@ $ cargo build --release
```
This will produce an executable in the `./target/release` subdirectory.
Note: if cargo fails to parse manifest try:
```bash
$ ~/.cargo/bin/cargo build --release
```
Note: When compiling a crate and you receive the following error:
```
error: the crate is compiled with the panic strategy `abort` which is incompatible with this crate's strategy of `unwind`
```
Cleaning the repository will most likely solve the issue, try:
```bash
$ cargo clean
```
This will always compile the latest nightly builds. If you want to build stable or beta, do a `git checkout stable` or `git checkout beta` first.
----

View File

@ -37,15 +37,12 @@ parity-hash-fetch = { path = "../hash-fetch" }
parity-reactor = { path = "../util/reactor" }
parity-ui = { path = "./ui" }
keccak-hash = { path = "../util/hash" }
clippy = { version = "0.0.103", optional = true}
parity-version = { path = "../util/version" }
[dev-dependencies]
env_logger = "0.4"
ethcore-devtools = { path = "../devtools" }
[features]
dev = ["clippy", "ethcore-util/dev"]
ui = ["parity-ui/no-precompiled-js"]
ui-precompiled = ["parity-ui/use-precompiled-js"]

View File

@ -18,13 +18,10 @@ quasi = { version = "0.32", default-features = false }
quasi_macros = { version = "0.32", optional = true }
syntex = { version = "0.58", optional = true }
syntex_syntax = { version = "0.58", optional = true }
clippy = { version = "0.0.103", optional = true }
[features]
dev = ["clippy"]
default = ["with-syntex"]
nightly = ["quasi_macros"]
nightly-testing = ["clippy"]
with-syntex = ["quasi/with-syntex", "quasi_codegen", "quasi_codegen/with-syntex", "syntex", "syntex_syntax"]
use-precompiled-js = []

View File

@ -193,7 +193,7 @@ const UPDATE_TIMEOUT_ERR_SECS: u64 = 60;
const UPDATE_TIMEOUT_INCOMPLETE_SECS: u64 = 10;
/// Maximal valid time drift.
pub const MAX_DRIFT: i64 = 500;
pub const MAX_DRIFT: i64 = 10_000;
type BoxFuture<A, B> = Box<Future<Item = A, Error = B> + Send>;

View File

@ -200,39 +200,57 @@ impl<R: URLHint + 'static, F: Fetch> Endpoint for ContentFetcher<F, R> {
Some(URLHintResult::Dapp(_)) if self.only_content => {
(None, Self::dapps_disabled(self.embeddable_on.clone()))
},
Some(URLHintResult::Dapp(dapp)) => {
let handler = ContentFetcherHandler::new(
req.method(),
&dapp.url(),
path,
installers::Dapp::new(
content_id.clone(),
self.cache_path.clone(),
Box::new(on_done),
self.embeddable_on.clone(),
self.pool.clone(),
),
self.embeddable_on.clone(),
self.fetch.clone(),
);
(Some(ContentStatus::Fetching(handler.fetch_control())), Box::new(handler) as endpoint::Response)
},
Some(URLHintResult::Content(content)) => {
let handler = ContentFetcherHandler::new(
req.method(),
&content.url,
path,
installers::Content::new(
content_id.clone(),
content.mime,
self.cache_path.clone(),
Box::new(on_done),
self.pool.clone(),
),
self.embeddable_on.clone(),
self.fetch.clone(),
);
Some(content) => {
let handler = match content {
URLHintResult::Dapp(dapp) => {
ContentFetcherHandler::new(
req.method(),
&dapp.url(),
path,
installers::Dapp::new(
content_id.clone(),
self.cache_path.clone(),
Box::new(on_done),
self.embeddable_on.clone(),
self.pool.clone(),
),
self.embeddable_on.clone(),
self.fetch.clone(),
)
},
URLHintResult::GithubDapp(content) => {
ContentFetcherHandler::new(
req.method(),
&content.url,
path,
installers::Dapp::new(
content_id.clone(),
self.cache_path.clone(),
Box::new(on_done),
self.embeddable_on.clone(),
self.pool.clone(),
),
self.embeddable_on.clone(),
self.fetch.clone(),
)
},
URLHintResult::Content(content) => {
ContentFetcherHandler::new(
req.method(),
&content.url,
path,
installers::Content::new(
content_id.clone(),
content.mime,
self.cache_path.clone(),
Box::new(on_done),
self.pool.clone(),
),
self.embeddable_on.clone(),
self.fetch.clone(),
)
},
};
(Some(ContentStatus::Fetching(handler.fetch_control())), Box::new(handler) as endpoint::Response)
},

View File

@ -19,7 +19,7 @@
use hyper::{self, mime, header};
use hyper::StatusCode;
use util::version;
use parity_version::version;
use handlers::add_security_headers;
use Embeddable;

View File

@ -16,8 +16,6 @@
//! Ethcore Webapplications for Parity
#![warn(missing_docs)]
#![cfg_attr(feature="nightly", feature(plugin))]
#![cfg_attr(feature="nightly", plugin(clippy))]
extern crate base32;
extern crate futures_cpupool;
@ -43,6 +41,7 @@ extern crate parity_dapps_glue as parity_dapps;
extern crate parity_hash_fetch as hash_fetch;
extern crate parity_ui;
extern crate keccak_hash as hash;
extern crate parity_version;
#[macro_use]
extern crate futures;

View File

@ -17,8 +17,9 @@
use std::io;
use std::time::{Duration, SystemTime};
use hyper::{self, header, StatusCode};
use hyper::mime::Mime;
use hyper::mime::{self, Mime};
use apps;
use handlers::{Reader, ContentHandler, add_security_headers};
use {Embeddable};
@ -95,7 +96,18 @@ impl<T: DappFile> PageHandler<T> {
add_security_headers(&mut headers, self.safe_to_embed_on);
}
let (reader, body) = Reader::pair(file.into_reader(), Vec::new());
let initial_content = if file.content_type().to_owned() == mime::TEXT_HTML {
let content = &format!(
r#"<script src="/{}/inject.js"></script>"#,
apps::UTILS_PATH,
);
content.as_bytes().to_vec()
} else {
Vec::new()
};
let (reader, body) = Reader::pair(file.into_reader(), initial_content);
res.set_body(body);
(Some(reader), res)
}

View File

@ -166,14 +166,15 @@ fn should_return_fetched_dapp_content() {
response1.assert_status("HTTP/1.1 200 OK");
assert_security_headers_for_embed(&response1.headers);
assert_eq!(
response1.body,
r#"18
assert!(
response1.body.contains(r#"18
<h1>Hello Gavcoin!</h1>
0
"#
"#),
"Expected Gavcoin body: {}",
response1.body
);
response2.assert_status("HTTP/1.1 200 OK");

View File

@ -60,3 +60,32 @@ fn should_serve_home() {
response.assert_header("Content-Type", "text/html");
assert_security_headers(&response.headers);
}
#[test]
fn should_inject_js() {
// given
let server = serve_ui();
// when
let response = request(server,
"\
GET / HTTP/1.1\r\n\
Host: 127.0.0.1:8080\r\n\
Connection: close\r\n\
\r\n\
{}
"
);
// then
response.assert_status("HTTP/1.1 200 OK");
response.assert_header("Content-Type", "text/html");
assert_eq!(
response.body.contains(r#"/inject.js"></script>"#),
true,
"Expected inject script tag in: {}",
response.body
);
assert_security_headers(&response.headers);
}

View File

@ -1,3 +1,35 @@
### Parity [v1.7.10](https://github.com/paritytech/parity/releases/tag/v1.7.10) (2017-12-11)
Parity 1.7.10 applies fixes for Proof-of-Authority networks and schedules the Kovan-Byzantium hard-fork.
- The Kovan testnet will fork on block `5067000` at `Thu Dec 14 2017 05:40:03 UTC`.
- This enables Byzantium features on Kovan.
- This disables uncles on Kovan for stability reasons.
- Proof-of-Authority networks are advised to set `maximumUncleCount` to 0 in a future `maximumUncleCountTransition` for stability reasons. See the [Kovan chain spec](https://github.com/paritytech/parity/blob/master/ethcore/res/ethereum/kovan.json) for an example. New PoA networks created with Parity will have this feature enabled by default.
The full list of included changes:
- Backports and HF block update ([#7243](https://github.com/paritytech/parity/pull/7243))
- Reduce max block timestamp drift to 15 seconds ([#7240](https://github.com/paritytech/parity/pull/7240))
- Add test for block timestamp validation within allowed drift
- Update kovan HF block number. ([#7259](https://github.com/paritytech/parity/pull/7259))
- [stable] Backports and Kovan HF ([#7235](https://github.com/paritytech/parity/pull/7235))
- Escape inifinite loop in estimte_gas ([#7075](https://github.com/paritytech/parity/pull/7075))
- Disable uncles by default ([#7006](https://github.com/paritytech/parity/pull/7006))
- Maximum uncle count transition ([#7196](https://github.com/paritytech/parity/pull/7196))
- Enable delayed maximum_uncle_count activation.
- Fix tests.
- Defer kovan HF.
- Bump version.
- Kovan HF.
- Update Kovan HF block.
- Fix compilation issues.
- Fix aura test.
- Add missing byzantium builtins.
- Fix tests.
- Bump version for installers.
- Increase allowed time drift to 10s. ([#7238](https://github.com/paritytech/parity/pull/7238))
### Parity [v1.7.9](https://github.com/paritytech/parity/releases/tag/v1.7.9) (2017-11-14)
Parity 1.7.9 removes the ability to deploy built-in multi-signature wallets.

View File

@ -11,7 +11,6 @@ ansi_term = "0.9"
bloomchain = "0.1"
bn = { git = "https://github.com/paritytech/bn" }
byteorder = "1.0"
clippy = { version = "0.0.103", optional = true}
common-types = { path = "types" }
crossbeam = "0.2.9"
ethash = { path = "../ethash" }
@ -83,6 +82,5 @@ evm-debug-tests = ["evm-debug"]
slow-blocks = [] # Use SLOW_TX_DURATION="50" (compile time!) to track transactions over 50ms
json-tests = []
test-heavy = []
dev = ["clippy"]
default = []
benches = []

View File

@ -32,7 +32,6 @@ macro_rules! overflowing {
}}
}
#[cfg_attr(feature="dev", allow(enum_variant_names))]
enum Request<Cost: ::evm::CostType> {
Gas(Cost),
GasMem(Cost, Cost),
@ -101,7 +100,6 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
}
}
#[cfg_attr(feature="dev", allow(cyclomatic_complexity))]
/// Determine how much gas is used by the given instruction, given the machine's state.
///
/// We guarantee that the final element of the returned tuple (`provided`) will be `Some`

View File

@ -66,7 +66,6 @@ struct CodeReader<'a> {
code: &'a [u8]
}
#[cfg_attr(feature="dev", allow(len_without_is_empty))]
impl<'a> CodeReader<'a> {
/// Create new code reader - starting at position 0.
@ -287,7 +286,6 @@ impl<Cost: CostType> Interpreter<Cost> {
}
}
#[cfg_attr(feature="dev", allow(too_many_arguments))]
fn exec_instruction(
&mut self,
gas: Cost,

View File

@ -0,0 +1,72 @@
{
"name": "Ellaism",
"dataDir": "ellaism",
"engine": {
"Ethash": {
"params": {
"minimumDifficulty": "0x020000",
"difficultyBoundDivisor": "0x0800",
"durationLimit": "0x0d",
"blockReward": "0x4563918244F40000",
"homesteadTransition": "0x0",
"bombDefuseTransition": "0x0",
"eip150Transition": "0x0",
"eip160Transition": "0x0",
"ecip1017EraRounds": 10000000,
"eip161abcTransition": "0x7fffffffffffffff",
"eip161dTransition": "0x7fffffffffffffff"
}
}
},
"params": {
"gasLimitBoundDivisor": "0x0400",
"registrar": "0x3bb2bb5c6c9c9b7f4EF430b47Dc7e026310042ea",
"accountStartNonce": "0x00",
"maximumExtraDataSize": "0x20",
"minGasLimit": "0x1388",
"networkID": "0x40",
"chainID": "0x40",
"eip155Transition": "0x0",
"eip98Transition": "0x7fffffffffffff",
"eip86Transition": "0x7fffffffffffff"
},
"genesis": {
"seal": {
"ethereum": {
"nonce": "0x0000000000000040",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
},
"difficulty": "0x40000000",
"author": "0x0000000000000000000000000000000000000000",
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x0000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x1388"
},
"nodes": [
"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 } } } }
}
}

View File

@ -173,6 +173,11 @@
"stateRoot": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544"
},
"nodes": [
"enode://5a62f19d35c0da8b576c9414568c728d4744e6e9d436c0f9db27456400011414f515871f13a6b8e0468534b5116cfe765d7630f680f1707a38467940a9f62511@45.55.33.62:30303",
"enode://605e04a43b1156966b3a3b66b980c87b7f18522f7f712035f84576016be909a2798a438b2b17b1a8c58db314d88539a77419ca4be36148c086900fba487c9d39@188.166.255.12:30303",
"enode://dc72806c3aa8fda207c8c018aba8d6cf143728b3628b6ded8d5e8cdeb8aa05cbd53f710ecd014c9a8f0d1e98f2874bff8afb15a229202f510a9c0258d1f6d109@159.203.210.80:30303",
"enode://01f76fa0561eca2b9a7e224378dd854278735f1449793c46ad0c4e79e8775d080c21dcc455be391e90a98153c3b05dcc8935c8440de7b56fe6d67251e33f4e3c@51.15.42.252:30303",
"enode://2c9059f05c352b29d559192fe6bca272d965c9f2290632a2cfda7f83da7d2634f3ec45ae3a72c54dd4204926fb8082dcf9686e0d7504257541c86fc8569bcf4b@163.172.171.38:30303",
"enode://efe4f2493f4aff2d641b1db8366b96ddacfe13e7a6e9c8f8f8cf49f9cdba0fdf3258d8c8f8d0c5db529f8123c8f1d95f36d54d590ca1bb366a5818b9a4ba521c@163.172.187.252:30303",
"enode://cd6611461840543d5b9c56fbf088736154c699c43973b3a1a32390cf27106f87e58a818a606ccb05f3866de95a4fe860786fea71bf891ea95f234480d3022aa3@163.172.157.114:30303",
"enode://bcc7240543fe2cf86f5e9093d05753dd83343f8fda7bf0e833f65985c73afccf8f981301e13ef49c4804491eab043647374df1c4adf85766af88a624ecc3330e@136.243.154.244:30303",
@ -184,13 +189,7 @@
"enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@52.16.188.185:30303",
"enode://de471bccee3d042261d52e9bff31458daecc406142b401d4cd848f677479f73104b9fdeb090af9583d3391b7f10cb2ba9e26865dd5fca4fcdc0fb1e3b723c786@54.94.239.50:30303",
"enode://1118980bf48b0a3640bdba04e0fe78b1add18e1cd99bf22d53daac1fd9972ad650df52176e7c7d89d1114cfef2bc23a2959aa54998a46afcf7d91809f0855082@52.74.57.123:30303",
"enode://4cd540b2c3292e17cff39922e864094bf8b0741fcc8c5dcea14957e389d7944c70278d872902e3d0345927f621547efa659013c400865485ab4bfa0c6596936f@138.201.144.135:30303",
"enode://89d5dc2a81e574c19d0465f497c1af96732d1b61a41de89c2a37f35707689ac416529fae1038809852b235c2d30fd325abdc57c122feeefbeaaf802cc7e9580d@45.55.33.62:30303",
"enode://605e04a43b1156966b3a3b66b980c87b7f18522f7f712035f84576016be909a2798a438b2b17b1a8c58db314d88539a77419ca4be36148c086900fba487c9d39@188.166.255.12:30303",
"enode://016b20125f447a3b203a3cae953b2ede8ffe51290c071e7599294be84317635730c397b8ff74404d6be412d539ee5bb5c3c700618723d3b53958c92bd33eaa82@159.203.210.80:30303",
"enode://01f76fa0561eca2b9a7e224378dd854278735f1449793c46ad0c4e79e8775d080c21dcc455be391e90a98153c3b05dcc8935c8440de7b56fe6d67251e33f4e3c@51.15.42.252:30303",
"enode://8d91c8137890d29110b9463882f17ae4e279cd2c90cf56573187ed1c8546fca5f590a9f05e9f108eb1bd91767ed01ede4daad9e001b61727885eaa246ddb39c2@163.172.171.38:30303"
"enode://4cd540b2c3292e17cff39922e864094bf8b0741fcc8c5dcea14957e389d7944c70278d872902e3d0345927f621547efa659013c400865485ab4bfa0c6596936f@138.201.144.135:30303"
],
"accounts": {
"0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },

View File

@ -12,19 +12,17 @@
"0x00427feae2419c15b89d1c21af10d1b6650a4d3d",
"0x4Ed9B08e6354C70fE6F8CB0411b0d3246b424d6c",
"0x0020ee4Be0e2027d76603cB751eE069519bA81A1",
"0x0010f94b296a852aaac52ea6c5ac72e03afd032d",
"0x007733a1FE69CF3f2CF989F81C7b4cAc1693387A",
"0x00E6d2b931F55a3f1701c7389d592a7778897879",
"0x00e4a10650e5a6D6001C38ff8E64F97016a1645c",
"0x00a0a24b9f0e5ec7aa4c7389b8302fd0123194de"
]
},
"validateScoreTransition": 1000000,
"validateStepTransition": 1500000,
"maximumUncleCount": 2
"maximumUncleCountTransition": 5067000,
"maximumUncleCount": 0
}
}
},
@ -38,7 +36,11 @@
"forkCanonHash": "0x0a66d93c2f727dca618fabaf70c39b37018c73d78b939d8b11efbbd09034778f",
"validateReceiptsTransition" : 1000000,
"eip155Transition": 1000000,
"validateChainIdTransition": 1000000
"validateChainIdTransition": 1000000,
"eip140Transition": 5067000,
"eip211Transition": 5067000,
"eip214Transition": 5067000,
"eip658Transition": 5067000
},
"genesis": {
"seal": {
@ -55,13 +57,17 @@
"0x0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
"0x0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
"0x0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
"0x0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": 5067000, "pricing": { "modexp": { "divisor": 20 } } } },
"0x0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": 5067000, "pricing": { "linear": { "base": 500, "word": 0 } } } },
"0x0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": 5067000, "pricing": { "linear": { "base": 40000, "word": 0 } } } },
"0x0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": 5067000, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } },
"0x00521965e7bd230323c423d96c657db5b79d099f": { "balance": "1606938044258990275541962092341162602522202993782792835301376" }
},
"nodes": [
"enode://0518a3d35d4a7b3e8c433e7ffd2355d84a1304ceb5ef349787b556197f0c87fad09daed760635b97d52179d645d3e6d16a37d2cc0a9945c2ddf585684beb39ac@40.68.248.100:30303",
"enode://dcf984764db421fa0cd8dc7fc02ae378545723abb94d179f55325514cc30185eaea3dcefde6e358b7cdbe970c50b7c49e841618713a9a72d6f3f59ad9949ec6b@52.165.239.18:30303",
"enode://56abaf065581a5985b8c5f4f88bd202526482761ba10be9bfdcd14846dd01f652ec33fde0f8c0fd1db19b59a4c04465681fcef50e11380ca88d25996191c52de@40.71.221.215:30303",
"enode://d07827483dc47b368eaf88454fb04b41b7452cf454e194e2bd4c14f98a3278fed5d819dbecd0d010407fc7688d941ee1e58d4f9c6354d3da3be92f55c17d7ce3@52.166.117.77:30303",
"enode://8fa162563a8e5a05eef3e1cd5abc5828c71344f7277bb788a395cce4a0e30baf2b34b92fe0b2dbbba2313ee40236bae2aab3c9811941b9f5a7e8e90aaa27ecba@52.165.239.18:30303",
"enode://7e2e7f00784f516939f94e22bdc6cf96153603ca2b5df1c7cc0f90a38e7a2f218ffb1c05b156835e8b49086d11fdd1b3e2965be16baa55204167aa9bf536a4d9@52.243.47.56:30303",
"enode://d51b3e98bf35addf2f1d0ea1ffc90483e24d7c60b0fb3be1701e818f3d6778c06e53fdec737a534fe222956296f9d6e909baa025916a94601897e5c7136a7d95@40.71.221.215:30303",
"enode://419d42e300e8fd379ff6d045d93d7e66a091441e7b3c9f1d3d10088d8634ad37721e6bf86148f78c3f1b9f1360dc566ca8ee830b2d2079bc9f7171ea6152bb64@52.166.117.77:30303"
"enode://0518a3d35d4a7b3e8c433e7ffd2355d84a1304ceb5ef349787b556197f0c87fad09daed760635b97d52179d645d3e6d16a37d2cc0a9945c2ddf585684beb39ac@40.68.248.100:30303"
]
}

@ -1 +1 @@
Subproject commit d6185ea16eaba7ff685c069c2064819f9549c4d7
Subproject commit d9d6133c1bc5dca4c74c9eb758a39546a0d46b45

View File

@ -22,7 +22,6 @@ pub type LogBloom = ::log_entry::LogBloom;
/// Constant 2048-bit datum for 0. Often used as a default.
pub static ZERO_LOGBLOOM: LogBloom = ::bigint::hash::H2048([0x00; 256]);
#[cfg_attr(feature="dev", allow(enum_variant_names))]
/// Semantic boolean for when a seal/signature is included.
pub enum Seal {
/// The seal/signature is included.

View File

@ -301,7 +301,6 @@ pub struct SealedBlock {
}
impl<'x> OpenBlock<'x> {
#[cfg_attr(feature="dev", allow(too_many_arguments))]
/// Create a new `OpenBlock` ready for transaction pushing.
pub fn new(
engine: &'x EthEngine,
@ -380,8 +379,13 @@ impl<'x> OpenBlock<'x> {
/// NOTE Will check chain constraints and the uncle number but will NOT check
/// that the header itself is actually valid.
pub fn push_uncle(&mut self, valid_uncle_header: Header) -> Result<(), BlockError> {
if self.block.uncles.len() + 1 > self.engine.maximum_uncle_count() {
return Err(BlockError::TooManyUncles(OutOfBounds{min: None, max: Some(self.engine.maximum_uncle_count()), found: self.block.uncles.len() + 1}));
let max_uncles = self.engine.maximum_uncle_count(self.block.header().number());
if self.block.uncles.len() + 1 > max_uncles {
return Err(BlockError::TooManyUncles(OutOfBounds{
min: None,
max: Some(max_uncles),
found: self.block.uncles.len() + 1,
}));
}
// TODO: check number
// TODO: check not a direct ancestor (use last_hashes for that)
@ -609,7 +613,6 @@ impl IsBlock for SealedBlock {
}
/// Enact the block given by block header, transactions and uncles
#[cfg_attr(feature="dev", allow(too_many_arguments))]
pub fn enact(
header: &Header,
transactions: &[SignedTransaction],
@ -683,7 +686,6 @@ fn push_transactions(block: &mut OpenBlock, transactions: &[SignedTransaction])
// TODO [ToDr] Pass `PreverifiedBlock` by move, this will avoid unecessary allocation
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header
#[cfg_attr(feature="dev", allow(too_many_arguments))]
pub fn enact_verified(
block: &PreverifiedBlock,
engine: &EthEngine,
@ -726,7 +728,6 @@ mod tests {
use transaction::SignedTransaction;
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header
#[cfg_attr(feature="dev", allow(too_many_arguments))]
fn enact_bytes(
block_bytes: &[u8],
engine: &EthEngine,
@ -773,7 +774,6 @@ mod tests {
}
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header. Seal the block aferwards
#[cfg_attr(feature="dev", allow(too_many_arguments))]
fn enact_and_seal(
block_bytes: &[u8],
engine: &EthEngine,

View File

@ -970,7 +970,6 @@ impl BlockChain {
self.cache_man.lock().note_used(CacheId::BlockDetails(block_hash));
}
#[cfg_attr(feature="dev", allow(similar_names))]
/// Inserts the block into backing cache database.
/// Expects the block to be valid and already verified.
/// If the block is already known, does nothing.
@ -1475,7 +1474,6 @@ impl BlockChain {
#[cfg(test)]
mod tests {
#![cfg_attr(feature="dev", allow(similar_names))]
use std::sync::Arc;
use rustc_hex::FromHex;
use hash::keccak;
@ -1583,7 +1581,6 @@ mod tests {
}
#[test]
#[cfg_attr(feature="dev", allow(cyclomatic_complexity))]
fn test_find_uncles() {
let mut canon_chain = ChainGenerator::default();
let mut finalizer = BlockFinalizer::default();
@ -1793,7 +1790,6 @@ mod tests {
}
#[test]
#[cfg_attr(feature="dev", allow(cyclomatic_complexity))]
fn test_small_fork() {
let mut canon_chain = ChainGenerator::default();
let mut finalizer = BlockFinalizer::default();

View File

@ -1855,7 +1855,7 @@ impl MiningBlockChainClient for Client {
let mut open_block = OpenBlock::new(
engine,
self.factories.clone(),
false, // TODO: this will need to be parameterised once we want to do immediate mining insertion.
self.tracedb.read().tracing_enabled(),
self.state_db.lock().boxed_clone_canon(&h),
best_header,
self.build_last_hashes(h.clone()),
@ -1870,7 +1870,7 @@ impl MiningBlockChainClient for Client {
.find_uncle_headers(&h, engine.maximum_uncle_age())
.unwrap_or_else(Vec::new)
.into_iter()
.take(engine.maximum_uncle_count())
.take(engine.maximum_uncle_count(open_block.header().number()))
.foreach(|h| {
open_block.push_uncle(h).expect("pushing maximum_uncle_count;
open_block was just created;
@ -1885,7 +1885,7 @@ impl MiningBlockChainClient for Client {
fn reopen_block(&self, block: ClosedBlock) -> OpenBlock {
let engine = &*self.engine;
let mut block = block.reopen(engine);
let max_uncles = engine.maximum_uncle_count();
let max_uncles = engine.maximum_uncle_count(block.header().number());
if block.uncles().len() < max_uncles {
let chain = self.chain.read();
let h = chain.best_block_hash();

View File

@ -51,8 +51,12 @@ mod finality;
/// `AuthorityRound` params.
pub struct AuthorityRoundParams {
/// Time to wait before next block or authority switching.
pub step_duration: Duration,
/// Time to wait before next block or authority switching,
/// in seconds.
///
/// Deliberately typed as u16 as too high of a value leads
/// to slow block issuance.
pub step_duration: u16,
/// Starting step,
pub start_step: Option<u64>,
/// Valid validators.
@ -65,20 +69,30 @@ pub struct AuthorityRoundParams {
pub immediate_transitions: bool,
/// Block reward in base units.
pub block_reward: U256,
/// Number of accepted uncles transition block.
pub maximum_uncle_count_transition: u64,
/// Number of accepted uncles.
pub maximum_uncle_count: usize,
}
const U16_MAX: usize = ::std::u16::MAX as usize;
impl From<ethjson::spec::AuthorityRoundParams> for AuthorityRoundParams {
fn from(p: ethjson::spec::AuthorityRoundParams) -> Self {
let mut step_duration_usize: usize = p.step_duration.into();
if step_duration_usize > U16_MAX {
step_duration_usize = U16_MAX;
warn!(target: "engine", "step_duration is too high ({}), setting it to {}", step_duration_usize, U16_MAX);
}
AuthorityRoundParams {
step_duration: Duration::from_secs(p.step_duration.into()),
step_duration: step_duration_usize as u16,
validators: new_validator_set(p.validators),
start_step: p.start_step.map(Into::into),
validate_score_transition: p.validate_score_transition.map_or(0, Into::into),
validate_step_transition: p.validate_step_transition.map_or(0, Into::into),
immediate_transitions: p.immediate_transitions.unwrap_or(false),
block_reward: p.block_reward.map_or_else(Default::default, Into::into),
maximum_uncle_count_transition: p.maximum_uncle_count_transition.map_or(0, Into::into),
maximum_uncle_count: p.maximum_uncle_count.map_or(0, Into::into),
}
}
@ -89,26 +103,47 @@ impl From<ethjson::spec::AuthorityRoundParams> for AuthorityRoundParams {
struct Step {
calibrate: bool, // whether calibration is enabled.
inner: AtomicUsize,
duration: Duration,
duration: u16,
}
impl Step {
fn load(&self) -> usize { self.inner.load(AtomicOrdering::SeqCst) }
fn duration_remaining(&self) -> Duration {
let now = unix_now();
let step_end = self.duration * (self.load() as u32 + 1);
if step_end > now {
step_end - now
} else {
Duration::from_secs(0)
let expected_seconds = (self.load() as u64)
.checked_add(1)
.and_then(|ctr| ctr.checked_mul(self.duration as u64));
match expected_seconds {
Some(secs) => {
let step_end = Duration::from_secs(secs);
if step_end > now {
step_end - now
} else {
Duration::from_secs(0)
}
},
None => {
let ctr = self.load();
error!(target: "engine", "Step counter is too high: {}, aborting", ctr);
panic!("step counter is too high: {}", ctr)
},
}
}
fn increment(&self) {
self.inner.fetch_add(1, AtomicOrdering::SeqCst);
use std::usize;
// fetch_add won't panic on overflow but will rather wrap
// around, leading to zero as the step counter, which might
// lead to unexpected situations, so it's better to shut down.
if self.inner.fetch_add(1, AtomicOrdering::SeqCst) == usize::MAX {
error!(target: "engine", "Step counter is too high: {}, aborting", usize::MAX);
panic!("step counter is too high: {}", usize::MAX);
}
}
fn calibrate(&self) {
if self.calibrate {
let new_step = unix_now().as_secs() / self.duration.as_secs();
let new_step = unix_now().as_secs() / (self.duration as u64);
self.inner.store(new_step as usize, AtomicOrdering::SeqCst);
}
}
@ -123,6 +158,11 @@ impl Step {
}
}
// Chain scoring: total weight is sqrt(U256::max_value())*height - step
fn calculate_score(parent_step: U256, current_step: U256) -> U256 {
U256::from(U128::max_value()) + parent_step - current_step
}
struct EpochManager {
epoch_transition_hash: H256,
epoch_transition_number: BlockNumber,
@ -221,6 +261,7 @@ pub struct AuthorityRound {
epoch_manager: Mutex<EpochManager>,
immediate_transitions: bool,
block_reward: U256,
maximum_uncle_count_transition: u64,
maximum_uncle_count: usize,
machine: EthereumMachine,
}
@ -350,8 +391,12 @@ impl AsMillis for Duration {
impl AuthorityRound {
/// Create a new instance of AuthorityRound engine.
pub fn new(our_params: AuthorityRoundParams, machine: EthereumMachine) -> Result<Arc<Self>, Error> {
if our_params.step_duration == 0 {
error!(target: "engine", "Authority Round step duration can't be zero, aborting");
panic!("authority_round: step duration can't be zero")
}
let should_timeout = our_params.start_step.is_none();
let initial_step = our_params.start_step.unwrap_or_else(|| (unix_now().as_secs() / our_params.step_duration.as_secs())) as usize;
let initial_step = our_params.start_step.unwrap_or_else(|| (unix_now().as_secs() / (our_params.step_duration as u64))) as usize;
let engine = Arc::new(
AuthorityRound {
transition_service: IoService::<()>::start()?,
@ -369,6 +414,7 @@ impl AuthorityRound {
epoch_manager: Mutex::new(EpochManager::blank()),
immediate_transitions: our_params.immediate_transitions,
block_reward: our_params.block_reward,
maximum_uncle_count_transition: our_params.maximum_uncle_count_transition,
maximum_uncle_count: our_params.maximum_uncle_count,
machine: machine,
});
@ -441,15 +487,23 @@ impl Engine<EthereumMachine> for AuthorityRound {
]
}
fn maximum_uncle_count(&self) -> usize { self.maximum_uncle_count }
fn maximum_uncle_count(&self, block: BlockNumber) -> usize {
if block >= self.maximum_uncle_count_transition {
self.maximum_uncle_count
} else {
// fallback to default value
2
}
}
fn populate_from_parent(&self, header: &mut Header, parent: &Header) {
// Chain scoring: total weight is sqrt(U256::max_value())*height - step
let new_difficulty = U256::from(U128::max_value()) + header_step(parent).expect("Header has been verified; qed").into() - self.step.load().into();
header.set_difficulty(new_difficulty);
let parent_step = header_step(parent).expect("Header has been verified; qed");
let score = calculate_score(parent_step.into(), self.step.load().into());
header.set_difficulty(score);
}
fn seals_internally(&self) -> Option<bool> {
// TODO: accept a `&Call` here so we can query the validator set.
Some(self.signer.read().is_some())
}
@ -457,14 +511,23 @@ impl Engine<EthereumMachine> for AuthorityRound {
///
/// This operation is synchronous and may (quite reasonably) not be available, in which case
/// `Seal::None` will be returned.
fn generate_seal(&self, block: &ExecutedBlock) -> Seal {
fn generate_seal(&self, block: &ExecutedBlock, parent: &Header) -> Seal {
// first check to avoid generating signature most of the time
// (but there's still a race to the `compare_and_swap`)
if !self.can_propose.load(AtomicOrdering::SeqCst) { return Seal::None; }
let header = block.header();
let parent_step: U256 = header_step(parent)
.expect("Header has been verified; qed").into();
let step = self.step.load();
let expected_diff = calculate_score(parent_step, step.into());
if header.difficulty() != &expected_diff {
return Seal::None;
}
// fetch correct validator set for current epoch, taking into account
// finality of previous transitions.
let active_set;
@ -491,6 +554,13 @@ impl Engine<EthereumMachine> for AuthorityRound {
};
if is_step_proposer(validators, header.parent_hash(), step, header.author()) {
// this is guarded against by `can_propose` unless the block was signed
// on the same step (implies same key) and on a different node.
if parent_step == step.into() {
warn!("Attempted to seal block on the same step as parent. Is this authority sealing with more than one node?");
return Seal::None;
}
if let Ok(signature) = self.sign(header.bare_hash()) {
trace!(target: "engine", "generate_seal: Issuing a block for step {}.", step);
@ -505,6 +575,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
trace!(target: "engine", "generate_seal: {} not a proposer for step {}.",
header.author(), step);
}
Seal::None
}
@ -546,7 +617,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
}
/// Check the number of seal fields.
fn verify_block_basic(&self, header: &Header,) -> Result<(), Error> {
fn verify_block_basic(&self, header: &Header) -> Result<(), Error> {
if header.number() >= self.validate_score_transition && *header.difficulty() >= U256::from(U128::max_value()) {
Err(From::from(BlockError::DifficultyOutOfBounds(
OutOfBounds { min: None, max: Some(U256::from(U128::max_value())), found: *header.difficulty() }
@ -857,17 +928,51 @@ mod tests {
let b2 = b2.close_and_lock();
engine.set_signer(tap.clone(), addr1, "1".into());
if let Seal::Regular(seal) = engine.generate_seal(b1.block()) {
if let Seal::Regular(seal) = engine.generate_seal(b1.block(), &genesis_header) {
assert!(b1.clone().try_seal(engine, seal).is_ok());
// Second proposal is forbidden.
assert!(engine.generate_seal(b1.block()) == Seal::None);
assert!(engine.generate_seal(b1.block(), &genesis_header) == Seal::None);
}
engine.set_signer(tap, addr2, "2".into());
if let Seal::Regular(seal) = engine.generate_seal(b2.block()) {
if let Seal::Regular(seal) = engine.generate_seal(b2.block(), &genesis_header) {
assert!(b2.clone().try_seal(engine, seal).is_ok());
// Second proposal is forbidden.
assert!(engine.generate_seal(b2.block()) == Seal::None);
assert!(engine.generate_seal(b2.block(), &genesis_header) == Seal::None);
}
}
#[test]
fn checks_difficulty_in_generate_seal() {
let tap = Arc::new(AccountProvider::transient_provider());
let addr1 = tap.insert_account(keccak("1").into(), "1").unwrap();
let addr2 = tap.insert_account(keccak("0").into(), "0").unwrap();
let spec = Spec::new_test_round();
let engine = &*spec.engine;
let genesis_header = spec.genesis_header();
let db1 = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap();
let db2 = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false).unwrap();
let b1 = b1.close_and_lock();
let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes, addr2, (3141562.into(), 31415620.into()), vec![], false).unwrap();
let b2 = b2.close_and_lock();
engine.set_signer(tap.clone(), addr1, "1".into());
match engine.generate_seal(b1.block(), &genesis_header) {
Seal::None | Seal::Proposal(_) => panic!("wrong seal"),
Seal::Regular(_) => {
engine.step();
engine.set_signer(tap.clone(), addr2, "0".into());
match engine.generate_seal(b2.block(), &genesis_header) {
Seal::Regular(_) | Seal::Proposal(_) => panic!("sealed despite wrong difficulty"),
Seal::None => {}
}
}
}
}
@ -950,12 +1055,13 @@ mod tests {
fn reports_skipped() {
let last_benign = Arc::new(AtomicUsize::new(0));
let params = AuthorityRoundParams {
step_duration: Default::default(),
step_duration: 1,
start_step: Some(1),
validators: Box::new(TestSet::new(Default::default(), last_benign.clone())),
validate_score_transition: 0,
validate_step_transition: 0,
immediate_transitions: true,
maximum_uncle_count_transition: 0,
maximum_uncle_count: 0,
block_reward: Default::default(),
};
@ -984,4 +1090,77 @@ mod tests {
assert!(aura.verify_block_family(&header, &parent_header).is_ok());
assert_eq!(last_benign.load(AtomicOrdering::SeqCst), 1);
}
#[test]
fn test_uncles_transition() {
let last_benign = Arc::new(AtomicUsize::new(0));
let params = AuthorityRoundParams {
step_duration: 1,
start_step: Some(1),
validators: Box::new(TestSet::new(Default::default(), last_benign.clone())),
validate_score_transition: 0,
validate_step_transition: 0,
immediate_transitions: true,
maximum_uncle_count_transition: 1,
maximum_uncle_count: 0,
block_reward: Default::default(),
};
let aura = {
let mut c_params = ::spec::CommonParams::default();
c_params.gas_limit_bound_divisor = 5.into();
let machine = ::machine::EthereumMachine::regular(c_params, Default::default());
AuthorityRound::new(params, machine).unwrap()
};
assert_eq!(aura.maximum_uncle_count(0), 2);
assert_eq!(aura.maximum_uncle_count(1), 0);
assert_eq!(aura.maximum_uncle_count(100), 0);
}
#[test]
#[should_panic(expected="counter is too high")]
fn test_counter_increment_too_high() {
use super::Step;
let step = Step {
calibrate: false,
inner: AtomicUsize::new(::std::usize::MAX),
duration: 1,
};
step.increment();
}
#[test]
#[should_panic(expected="counter is too high")]
fn test_counter_duration_remaining_too_high() {
use super::Step;
let step = Step {
calibrate: false,
inner: AtomicUsize::new(::std::usize::MAX),
duration: 1,
};
step.duration_remaining();
}
#[test]
#[should_panic(expected="authority_round: step duration can't be zero")]
fn test_step_duration_zero() {
let last_benign = Arc::new(AtomicUsize::new(0));
let params = AuthorityRoundParams {
step_duration: 0,
start_step: Some(1),
validators: Box::new(TestSet::new(Default::default(), last_benign.clone())),
validate_score_transition: 0,
validate_step_transition: 0,
immediate_transitions: true,
maximum_uncle_count_transition: 0,
maximum_uncle_count: 0,
block_reward: Default::default(),
};
let mut c_params = ::spec::CommonParams::default();
c_params.gas_limit_bound_divisor = 5.into();
let machine = ::machine::EthereumMachine::regular(c_params, Default::default());
AuthorityRound::new(params, machine).unwrap();
}
}

View File

@ -107,7 +107,7 @@ impl Engine<EthereumMachine> for BasicAuthority {
}
/// Attempt to seal the block internally.
fn generate_seal(&self, block: &ExecutedBlock) -> Seal {
fn generate_seal(&self, block: &ExecutedBlock, _parent: &Header) -> Seal {
let header = block.header();
let author = header.author();
if self.validators.contains(header.parent_hash(), author) {
@ -251,7 +251,7 @@ mod tests {
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![], false).unwrap();
let b = b.close_and_lock();
if let Seal::Regular(seal) = engine.generate_seal(b.block()) {
if let Seal::Regular(seal) = engine.generate_seal(b.block(), &genesis_header) {
assert!(b.try_seal(engine, seal).is_ok());
}
}

View File

@ -43,7 +43,7 @@ impl<M: Machine> Engine<M> for InstantSeal<M>
fn seals_internally(&self) -> Option<bool> { Some(true) }
fn generate_seal(&self, block: &M::LiveBlock) -> Seal {
fn generate_seal(&self, block: &M::LiveBlock, _parent: &M::Header) -> Seal {
if block.transactions().is_empty() { Seal::None } else { Seal::Regular(Vec::new()) }
}
@ -72,7 +72,7 @@ mod tests {
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::default(), (3141562.into(), 31415620.into()), vec![], false).unwrap();
let b = b.close_and_lock();
if let Seal::Regular(seal) = engine.generate_seal(b.block()) {
if let Seal::Regular(seal) = engine.generate_seal(b.block(), &genesis_header) {
assert!(b.try_seal(engine, seal).is_ok());
}
}

View File

@ -192,7 +192,8 @@ pub trait Engine<M: Machine>: Sync + Send {
fn extra_info(&self, _header: &M::Header) -> BTreeMap<String, String> { BTreeMap::new() }
/// Maximum number of uncles a block is allowed to declare.
fn maximum_uncle_count(&self) -> usize { 0 }
fn maximum_uncle_count(&self, _block: BlockNumber) -> usize { 0 }
/// The number of generations back that uncles can be.
fn maximum_uncle_age(&self) -> usize { 6 }
@ -225,7 +226,7 @@ pub trait Engine<M: Machine>: Sync + Send {
///
/// It is fine to require access to state or a full client for this function, since
/// light clients do not generate seals.
fn generate_seal(&self, _block: &M::LiveBlock) -> Seal { Seal::None }
fn generate_seal(&self, _block: &M::LiveBlock, _parent: &M::Header) -> Seal { Seal::None }
/// Verify a locally-generated seal of a header.
///
@ -363,7 +364,7 @@ pub trait EthEngine: Engine<::machine::EthereumMachine> {
}
/// The nonce with which accounts begin at given block.
fn account_start_nonce(&self, block: u64) -> U256 {
fn account_start_nonce(&self, block: BlockNumber) -> U256 {
self.machine().account_start_nonce(block)
}

View File

@ -16,6 +16,7 @@
use bigint::prelude::U256;
use engines::Engine;
use header::BlockNumber;
use parity_machine::{Header, LiveBlock, WithBalances};
/// Params for a null engine.
@ -95,7 +96,7 @@ impl<M: WithBalances> Engine<M> for NullEngine<M> {
self.machine.note_rewards(block, &[(author, result_block_reward)], &uncle_rewards)
}
fn maximum_uncle_count(&self) -> usize { 2 }
fn maximum_uncle_count(&self, _block: BlockNumber) -> usize { 2 }
fn verify_local_seal(&self, _header: &M::Header) -> Result<(), M::Error> {
Ok(())

View File

@ -450,7 +450,7 @@ impl Engine<EthereumMachine> for Tendermint {
fn machine(&self) -> &EthereumMachine { &self.machine }
fn maximum_uncle_count(&self) -> usize { 0 }
fn maximum_uncle_count(&self, _block: BlockNumber) -> usize { 0 }
fn maximum_uncle_age(&self) -> usize { 0 }
@ -483,7 +483,7 @@ impl Engine<EthereumMachine> for Tendermint {
///
/// This operation is synchronous and may (quite reasonably) not be available, in which case
/// `Seal::None` will be returned.
fn generate_seal(&self, block: &ExecutedBlock) -> Seal {
fn generate_seal(&self, block: &ExecutedBlock, _parent: &Header) -> Seal {
let header = block.header();
let author = header.author();
// Only proposer can generate seal if None was generated.
@ -805,7 +805,7 @@ mod tests {
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b = OpenBlock::new(spec.engine.as_ref(), Default::default(), false, db.boxed_clone(), &genesis_header, last_hashes, proposer, (3141562.into(), 31415620.into()), vec![], false).unwrap();
let b = b.close();
if let Seal::Proposal(seal) = spec.engine.generate_seal(b.block()) {
if let Seal::Proposal(seal) = spec.engine.generate_seal(b.block(), &genesis_header) {
(b, seal)
} else {
panic!()

View File

@ -58,7 +58,7 @@ impl ValidatorContract {
let client = self.client.read().clone();
Box::new(move |a, d| client.as_ref()
.and_then(Weak::upgrade)
.ok_or("No client!".into())
.ok_or_else(|| "No client!".into())
.and_then(|c| {
match c.as_full_client() {
Some(c) => c.transact_contract(a, d)

View File

@ -138,7 +138,7 @@ impl ValidatorSet for Multi {
}
*self.block_number.write() = Box::new(move |id| client
.upgrade()
.ok_or("No client!".into())
.ok_or_else(|| "No client!".into())
.and_then(|c| c.block_number(id).ok_or("Unknown block".into())));
}
}

View File

@ -311,7 +311,7 @@ impl ValidatorSet for ValidatorSafeContract {
let client = self.client.read().clone();
Box::new(move |addr, data| client.as_ref()
.and_then(Weak::upgrade)
.ok_or("No client!".into())
.ok_or_else(|| "No client!".into())
.and_then(|c| {
match c.as_full_client() {
Some(c) => c.call_contract(id, addr, data),

View File

@ -26,7 +26,7 @@ use util::Address;
use unexpected::{OutOfBounds, Mismatch};
use block::*;
use error::{BlockError, Error};
use header::Header;
use header::{Header, BlockNumber};
use engines::{self, Engine};
use ethjson;
use rlp::{self, UntrustedRlp};
@ -181,7 +181,7 @@ impl Engine<EthereumMachine> for Arc<Ethash> {
}
}
fn maximum_uncle_count(&self) -> usize { 2 }
fn maximum_uncle_count(&self, _block: BlockNumber) -> usize { 2 }
fn populate_from_parent(&self, header: &mut Header, parent: &Header) {
let difficulty = self.calculate_difficulty(header, parent);
@ -336,7 +336,6 @@ impl Engine<EthereumMachine> for Arc<Ethash> {
}
}
#[cfg_attr(feature="dev", allow(wrong_self_convention))]
impl Ethash {
fn calculate_difficulty(&self, header: &Header, parent: &Header) -> U256 {
const EXP_DIFF_PERIOD: u64 = 100_000;
@ -520,7 +519,7 @@ mod tests {
let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, start_reward, block_number);
assert_eq!(15, eras);
assert_eq!(U256::from_str("271000000000000").unwrap(), reward);
let block_number = 250000000;
let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, start_reward, block_number);
assert_eq!(49, eras);

View File

@ -75,6 +75,11 @@ pub fn new_musicoin<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/musicoin.json"))
}
/// Create a new Ellaism mainnet chain spec.
pub fn new_ellaism<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/ellaism.json"))
}
/// Create a new Kovan testnet chain spec.
pub fn new_kovan<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/kovan.json"))

View File

@ -85,7 +85,6 @@ impl<'a, T: 'a, V: 'a, B: 'a> Externalities<'a, T, V, B>
where T: Tracer, V: VMTracer, B: StateBackend
{
/// Basic `Externalities` constructor.
#[cfg_attr(feature="dev", allow(too_many_arguments))]
pub fn new(state: &'a mut State<B>,
env_info: &'a EnvInfo,
machine: &'a Machine,
@ -302,7 +301,6 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
Ok(self.state.code_size(address)?.unwrap_or(0))
}
#[cfg_attr(feature="dev", allow(match_ref_pats))]
fn ret(mut self, gas: &U256, data: &ReturnData, apply_state: bool) -> vm::Result<U256>
where Self: Sized {
let handle_copy = |to: &mut Option<&mut Bytes>| {

View File

@ -16,23 +16,6 @@
#![warn(missing_docs)]
#![cfg_attr(feature="benches", feature(test))]
#![cfg_attr(feature="dev", feature(plugin))]
#![cfg_attr(feature="dev", plugin(clippy))]
// Clippy settings
// Most of the time much more readable
#![cfg_attr(feature="dev", allow(needless_range_loop))]
// Shorter than if-else
#![cfg_attr(feature="dev", allow(match_bool))]
// Keeps consistency (all lines with `.clone()`).
#![cfg_attr(feature="dev", allow(clone_on_copy))]
// Complains on Box<E> when implementing From<Box<E>>
#![cfg_attr(feature="dev", allow(boxed_local))]
// Complains about nested modules with same name as parent
#![cfg_attr(feature="dev", allow(module_inception))]
// TODO [todr] a lot of warnings to be fixed
#![cfg_attr(feature="dev", allow(assign_op_pattern))]
//! Ethcore library
//!

View File

@ -366,7 +366,6 @@ impl Miner {
)
}
#[cfg_attr(feature="dev", allow(match_same_arms))]
/// Prepares new block for sealing including top transactions from queue.
fn prepare_block(&self, chain: &MiningBlockChainClient) -> (ClosedBlock, Option<H256>) {
let _timer = PerfTimer::new("prepare_block");
@ -534,7 +533,13 @@ impl Miner {
fn seal_and_import_block_internally(&self, chain: &MiningBlockChainClient, block: ClosedBlock) -> bool {
if !block.transactions().is_empty() || self.forced_sealing() || Instant::now() > *self.next_mandatory_reseal.read() {
trace!(target: "miner", "seal_block_internally: attempting internal seal.");
match self.engine.generate_seal(block.block()) {
let parent_header = match chain.block_header(BlockId::Hash(*block.header().parent_hash())) {
Some(hdr) => hdr.decode(),
None => return false,
};
match self.engine.generate_seal(block.block(), &parent_header) {
// Save proposal for later seal submission and broadcast it.
Seal::Proposal(seal) => {
trace!(target: "miner", "Received a Proposal seal.");
@ -702,8 +707,6 @@ impl Miner {
/// Are we allowed to do a non-mandatory reseal?
fn tx_reseal_allowed(&self) -> bool { Instant::now() > *self.next_allowed_reseal.lock() }
#[cfg_attr(feature="dev", allow(wrong_self_convention))]
#[cfg_attr(feature="dev", allow(redundant_closure))]
fn from_pending_block<H, F, G>(&self, latest_block_number: BlockNumber, from_chain: F, map_block: G) -> H
where F: Fn() -> H, G: FnOnce(&ClosedBlock) -> H {
let sealing_work = self.sealing_work.lock();
@ -863,7 +866,6 @@ impl MinerService for Miner {
results
}
#[cfg_attr(feature="dev", allow(collapsible_if))]
fn import_own_transaction(
&self,
chain: &MiningBlockChainClient,

View File

@ -15,8 +15,6 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
#![warn(missing_docs)]
#![cfg_attr(all(nightly, feature="dev"), feature(plugin))]
#![cfg_attr(all(nightly, feature="dev"), plugin(clippy))]
//! Miner module
//! Keeps track of transactions and mined block.

View File

@ -136,7 +136,6 @@ impl PartialOrd for TransactionOrigin {
}
impl Ord for TransactionOrigin {
#[cfg_attr(feature="dev", allow(match_same_arms))]
fn cmp(&self, other: &TransactionOrigin) -> Ordering {
if *other == *self {
return Ordering::Equal;
@ -516,7 +515,6 @@ pub struct AccountDetails {
const GAS_PRICE_BUMP_SHIFT: usize = 3; // 2 = 25%, 3 = 12.5%, 4 = 6.25%
/// Describes the strategy used to prioritize transactions in the queue.
#[cfg_attr(feature="dev", allow(enum_variant_names))]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum PrioritizationStrategy {
/// Use only gas price. Disregards the actual computation cost of the transaction.

View File

@ -186,7 +186,6 @@ impl IoHandler<ClientIoMessage> for ClientIoHandler {
}
}
#[cfg_attr(feature="dev", allow(single_match))]
fn message(&self, _io: &IoContext<ClientIoMessage>, net_message: &ClientIoMessage) {
use std::thread;

View File

@ -57,7 +57,6 @@ impl StateProducer {
}
}
#[cfg_attr(feature="dev", allow(let_and_return))]
/// Tick the state producer. This alters the state, writing new data into
/// the database.
pub fn tick<R: Rng>(&mut self, rng: &mut R, db: &mut HashDB) {

View File

@ -35,6 +35,15 @@ use std::cell::{RefCell, Cell};
const STORAGE_CACHE_ITEMS: usize = 8192;
/// Boolean type for clean/dirty status.
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum Filth {
/// Data has not been changed.
Clean,
/// Data has been changed.
Dirty,
}
/// Single account in the system.
/// Keeps track of changes to the code and storage.
/// The changes are applied in `commit_storage` and `commit_code`

View File

@ -604,7 +604,6 @@ impl<B: Backend> State<B> {
}
/// Add `incr` to the balance of account `a`.
#[cfg_attr(feature="dev", allow(single_match))]
pub fn add_balance(&mut self, a: &Address, incr: &U256, cleanup_mode: CleanupMode) -> trie::Result<()> {
trace!(target: "state", "add_balance({}, {}): {}", a, incr, self.balance(a)?);
let is_value_transfer = !incr.is_zero();
@ -744,8 +743,6 @@ impl<B: Backend> State<B> {
}
/// Commits our cached account changes into the trie.
#[cfg_attr(feature="dev", allow(match_ref_pats))]
#[cfg_attr(feature="dev", allow(needless_borrow))]
pub fn commit(&mut self) -> Result<(), Error> {
// first, commit the sub trees.
let mut accounts = self.cache.borrow_mut();

View File

@ -58,7 +58,6 @@ impl Substate {
}
/// Get the cleanup mode object from this.
#[cfg_attr(feature="dev", allow(wrong_self_convention))]
pub fn to_cleanup_mode(&mut self, schedule: &Schedule) -> CleanupMode {
match (schedule.kill_dust != CleanDustMode::Off, schedule.no_empty, schedule.kill_empty) {
(false, false, _) => CleanupMode::ForceCreate,

View File

@ -427,7 +427,6 @@ impl state::Backend for StateDB {
cache.accounts.get_mut(addr).map(|a| a.as_ref().map(|a| a.clone_basic()))
}
#[cfg_attr(feature="dev", allow(map_clone))]
fn get_cached_code(&self, hash: &H256) -> Option<Arc<Vec<u8>>> {
let mut cache = self.code_cache.lock();

View File

@ -34,7 +34,6 @@ use cache_manager::CacheManager;
const TRACE_DB_VER: &'static [u8] = b"1.0";
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature="dev", allow(enum_variant_names))]
enum TraceDBIndex {
/// Block traces index.
BlockTraces = 0,

View File

@ -164,7 +164,6 @@ struct QueueSignal {
}
impl QueueSignal {
#[cfg_attr(feature="dev", allow(bool_comparison))]
fn set_sync(&self) {
// Do not signal when we are about to close
if self.deleting.load(AtomicOrdering::Relaxed) {
@ -179,7 +178,6 @@ impl QueueSignal {
}
}
#[cfg_attr(feature="dev", allow(bool_comparison))]
fn set_async(&self) {
// Do not signal when we are about to close
if self.deleting.load(AtomicOrdering::Relaxed) {

View File

@ -137,9 +137,14 @@ pub fn verify_block_family(header: &Header, parent: &Header, engine: &EthEngine,
fn verify_uncles(header: &Header, bytes: &[u8], bc: &BlockProvider, engine: &EthEngine) -> Result<(), Error> {
let num_uncles = UntrustedRlp::new(bytes).at(2)?.item_count()?;
let max_uncles = engine.maximum_uncle_count(header.number());
if num_uncles != 0 {
if num_uncles > engine.maximum_uncle_count() {
return Err(From::from(BlockError::TooManyUncles(OutOfBounds { min: None, max: Some(engine.maximum_uncle_count()), found: num_uncles })));
if num_uncles > max_uncles {
return Err(From::from(BlockError::TooManyUncles(OutOfBounds {
min: None,
max: Some(max_uncles),
found: num_uncles,
})));
}
let mut excluded = HashSet::new();
@ -268,7 +273,7 @@ pub fn verify_header_params(header: &Header, engine: &EthEngine, is_full: bool)
}
if is_full {
let max_time = get_time().sec as u64 + 30;
let max_time = get_time().sec as u64 + 15;
if header.timestamp() > max_time {
return Err(From::from(BlockError::InvalidTimestamp(OutOfBounds { max: Some(max_time), min: None, found: header.timestamp() })))
}
@ -493,7 +498,6 @@ mod tests {
}
#[test]
#[cfg_attr(feature="dev", allow(similar_names))]
fn test_verify_block() {
use rlp::RlpStream;
@ -641,9 +645,15 @@ mod tests {
check_fail_timestamp(basic_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine));
header = good.clone();
header.set_timestamp(get_time().sec as u64 + 40);
header.set_timestamp(get_time().sec as u64 + 20);
check_fail_timestamp(basic_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine));
header = good.clone();
header.set_timestamp(get_time().sec as u64 + 10);
header.set_uncles_hash(good_uncles_hash.clone());
header.set_transactions_root(good_transactions_root.clone());
check_ok(basic_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine));
header = good.clone();
header.set_number(9);
check_fail(family_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine, &bc),
@ -653,7 +663,7 @@ mod tests {
let mut bad_uncles = good_uncles.clone();
bad_uncles.push(good_uncle1.clone());
check_fail(family_test(&create_test_block_with_data(&header, &good_transactions, &bad_uncles), engine, &bc),
TooManyUncles(OutOfBounds { max: Some(engine.maximum_uncle_count()), min: None, found: bad_uncles.len() }));
TooManyUncles(OutOfBounds { max: Some(engine.maximum_uncle_count(header.number())), min: None, found: bad_uncles.len() }));
header = good.clone();
bad_uncles = vec![ good_uncle1.clone(), good_uncle1.clone() ];

View File

@ -96,7 +96,6 @@ pub trait Ext {
/// Returns Err, if we run out of gas.
/// Otherwise returns call_result which contains gas left
/// and true if subcall was successfull.
#[cfg_attr(feature="dev", allow(too_many_arguments))]
fn call(&mut self,
gas: &U256,
sender_address: &Address,

View File

@ -69,17 +69,17 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
),
Static(
"_ccall",
&[I32; 6],
&[I64, I32, I32, I32, I32, I32, I32],
Some(I32),
),
Static(
"_dcall",
&[I32; 5],
&[I64, I32, I32, I32, I32, I32],
Some(I32),
),
Static(
"_scall",
&[I32; 5],
&[I64, I32, I32, I32, I32, I32],
Some(I32),
),
Static(

View File

@ -111,6 +111,7 @@ impl vm::Vm for WasmInterpreter {
address: params.address,
sender: params.sender,
origin: params.origin,
code_address: params.code_address,
value: params.value.value(),
},
&self.program,

View File

@ -104,6 +104,7 @@ pub struct RuntimeContext {
pub address: Address,
pub sender: Address,
pub origin: Address,
pub code_address: Address,
pub value: U256,
}
@ -305,6 +306,7 @@ impl<'a, 'b> Runtime<'a, 'b> {
//
// method signature:
// fn (
// gas: i64,
// address: *const u8,
// val_ptr: *const u8,
// input_ptr: *const u8,
@ -323,6 +325,7 @@ impl<'a, 'b> Runtime<'a, 'b> {
//
// signature (same as static call):
// fn (
// gas: i64,
// address: *const u8,
// input_ptr: *const u8,
// input_len: u32,
@ -330,7 +333,7 @@ impl<'a, 'b> Runtime<'a, 'b> {
// result_len: u32,
// ) -> i32
self.do_call(false, CallType::CallCode, context)
self.do_call(false, CallType::DelegateCall, context)
}
fn do_call(
@ -363,6 +366,9 @@ impl<'a, 'b> Runtime<'a, 'b> {
let address = self.pop_address(&mut context)?;
trace!(target: "wasm", " address: {:?}", address);
let gas = context.value_stack.pop_as::<i64>()? as u64;
trace!(target: "wasm", " gas: {:?}", gas);
if let Some(ref val) = val {
let address_balance = self.ext.balance(&self.context.address)
.map_err(|_| UserTrap::BalanceQueryError)?;
@ -377,16 +383,16 @@ impl<'a, 'b> Runtime<'a, 'b> {
let mut result = Vec::with_capacity(result_alloc_len as usize);
result.resize(result_alloc_len as usize, 0);
let gas = self.gas_left()
.map_err(|_| UserTrap::InvalidGasState)?
.into();
// todo: optimize to use memory views once it's in
let payload = self.memory.get(input_ptr, input_len as usize)?;
self.charge(|_| gas.into())?;
let call_result = self.ext.call(
&gas,
&self.context.sender,
&self.context.address,
&gas.into(),
match call_type { CallType::DelegateCall => &self.context.sender, _ => &self.context.address },
match call_type { CallType::Call | CallType::StaticCall => &address, _ => &self.context.address },
val,
&payload,
&address,
@ -396,12 +402,16 @@ impl<'a, 'b> Runtime<'a, 'b> {
match call_result {
vm::MessageCallResult::Success(gas_left, _) => {
self.gas_counter = self.gas_limit - gas_left.low_u64();
// cannot overflow, before making call gas_counter was incremented with gas, and gas_left < gas
self.gas_counter = self.gas_counter - gas_left.low_u64();
self.memory.set(result_ptr, &result)?;
Ok(Some(0i32.into()))
},
vm::MessageCallResult::Reverted(gas_left, _) => {
self.gas_counter = self.gas_limit - gas_left.low_u64();
// cannot overflow, before making call gas_counter was incremented with gas, and gas_left < gas
self.gas_counter = self.gas_counter - gas_left.low_u64();
self.memory.set(result_ptr, &result)?;
Ok(Some((-1i32).into()))
},
@ -416,6 +426,7 @@ impl<'a, 'b> Runtime<'a, 'b> {
{
// signature (same as code call):
// fn (
// gas: i64,
// address: *const u8,
// input_ptr: *const u8,
// input_len: u32,

View File

@ -60,7 +60,7 @@ fn empty() {
test_finalize(interpreter.exec(params, &mut ext)).unwrap()
};
assert_eq!(gas_left, U256::from(99_982));
assert_eq!(gas_left, U256::from(96_678));
}
// This test checks if the contract deserializes payload header properly.
@ -112,7 +112,7 @@ fn logger() {
U256::from(1_000_000_000),
"Logger sets 0x04 key to the trasferred value"
);
assert_eq!(gas_left, U256::from(19_147));
assert_eq!(gas_left, U256::from(15_860));
}
// This test checks if the contract can allocate memory and pass pointer to the result stream properly.
@ -147,7 +147,7 @@ fn identity() {
sender,
"Idenity test contract does not return the sender passed"
);
assert_eq!(gas_left, U256::from(99_844));
assert_eq!(gas_left, U256::from(96_540));
}
// Dispersion test sends byte array and expect the contract to 'disperse' the original elements with
@ -180,7 +180,7 @@ fn dispersion() {
result,
vec![0u8, 0, 125, 11, 197, 7, 255, 8, 19, 0]
);
assert_eq!(gas_left, U256::from(96_393));
assert_eq!(gas_left, U256::from(96_116));
}
#[test]
@ -208,7 +208,7 @@ fn suicide_not() {
result,
vec![0u8]
);
assert_eq!(gas_left, U256::from(96_725));
assert_eq!(gas_left, U256::from(96_461));
}
#[test]
@ -240,7 +240,7 @@ fn suicide() {
};
assert!(ext.suicides.contains(&refund));
assert_eq!(gas_left, U256::from(96_687));
assert_eq!(gas_left, U256::from(96_429));
}
#[test]
@ -270,7 +270,7 @@ fn create() {
assert!(ext.calls.contains(
&FakeCall {
call_type: FakeCallType::Create,
gas: U256::from(65_899),
gas: U256::from(62_545),
sender_address: None,
receive_address: None,
value: Some(1_000_000_000.into()),
@ -278,9 +278,52 @@ fn create() {
code_address: None,
}
));
assert_eq!(gas_left, U256::from(65_892));
assert_eq!(gas_left, U256::from(62_538));
}
#[test]
fn call_msg() {
::ethcore_logger::init_log();
let sender: Address = "01030507090b0d0f11131517191b1d1f21232527".parse().unwrap();
let receiver: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap();
let contract_address: Address = "0d461d4174b4ae35775c4a342f1e5e1e4e6c4db5".parse().unwrap();
let mut params = ActionParams::default();
params.sender = sender.clone();
params.address = receiver.clone();
params.code_address = contract_address.clone();
params.gas = U256::from(100_000);
params.code = Some(Arc::new(load_sample!("call.wasm")));
params.data = Some(Vec::new());
let mut ext = FakeExt::new();
ext.balances.insert(receiver.clone(), U256::from(10000000000u64));
let gas_left = {
let mut interpreter = wasm_interpreter();
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
match result {
GasLeft::Known(gas_left) => gas_left,
GasLeft::NeedsReturn { .. } => { panic!("Call test should not return payload"); },
}
};
trace!(target: "wasm", "fake_calls: {:?}", &ext.calls);
assert!(ext.calls.contains(
&FakeCall {
call_type: FakeCallType::Call,
gas: U256::from(33_000),
sender_address: Some(receiver),
receive_address: Some(Address::from([99, 88, 77, 66, 55, 44, 33, 22, 11, 0, 11, 22, 33, 44, 55, 66, 77, 88, 99, 0])),
value: Some(1000000000.into()),
data: vec![129u8, 123, 113, 107, 101, 97],
code_address: Some(Address::from([99, 88, 77, 66, 55, 44, 33, 22, 11, 0, 11, 22, 33, 44, 55, 66, 77, 88, 99, 0])),
}
));
assert_eq!(gas_left, U256::from(95_699));
}
#[test]
fn call_code() {
@ -312,7 +355,7 @@ fn call_code() {
assert!(ext.calls.contains(
&FakeCall {
call_type: FakeCallType::Call,
gas: U256::from(98_713),
gas: U256::from(20_000),
sender_address: Some(sender),
receive_address: Some(receiver),
value: None,
@ -324,7 +367,7 @@ fn call_code() {
// siphash result
let res = LittleEndian::read_u32(&result[..]);
assert_eq!(res, 4198595614);
assert_eq!(gas_left, U256::from(93_855));
assert_eq!(gas_left, U256::from(90_550));
}
#[test]
@ -333,6 +376,7 @@ fn call_static() {
let sender: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap();
let receiver: Address = "01030507090b0d0f11131517191b1d1f21232527".parse().unwrap();
let contract_address: Address = "0d461d4174b4ae35775c4a342f1e5e1e4e6c4db5".parse().unwrap();
let mut params = ActionParams::default();
params.sender = sender.clone();
@ -341,6 +385,7 @@ fn call_static() {
params.code = Some(Arc::new(load_sample!("call_static.wasm")));
params.data = Some(Vec::new());
params.value = ActionValue::transfer(1_000_000_000);
params.code_address = contract_address.clone();
let mut ext = FakeExt::new();
@ -357,9 +402,9 @@ fn call_static() {
assert!(ext.calls.contains(
&FakeCall {
call_type: FakeCallType::Call,
gas: U256::from(98_713),
sender_address: Some(sender),
receive_address: Some(receiver),
gas: U256::from(20_000),
sender_address: Some(receiver),
receive_address: Some("13077bfb00000000000000000000000000000000".parse().unwrap()),
value: None,
data: vec![1u8, 2, 3, 5, 7, 11],
code_address: Some("13077bfb00000000000000000000000000000000".parse().unwrap()),
@ -370,7 +415,7 @@ fn call_static() {
let res = LittleEndian::read_u32(&result[..]);
assert_eq!(res, 317632590);
assert_eq!(gas_left, U256::from(93_855));
assert_eq!(gas_left, U256::from(90_550));
}
// Realloc test
@ -393,7 +438,7 @@ fn realloc() {
}
};
assert_eq!(result, vec![0u8; 2]);
assert_eq!(gas_left, U256::from(96_723));
assert_eq!(gas_left, U256::from(96_445));
}
// Tests that contract's ability to read from a storage
@ -419,7 +464,7 @@ fn storage_read() {
};
assert_eq!(Address::from(&result[12..32]), address);
assert_eq!(gas_left, U256::from(99_767));
assert_eq!(gas_left, U256::from(96_463));
}
// Tests keccak calculation
@ -445,7 +490,7 @@ fn keccak() {
};
assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87"));
assert_eq!(gas_left, U256::from(81_446));
assert_eq!(gas_left, U256::from(81_067));
}
// memcpy test.
@ -477,7 +522,7 @@ fn memcpy() {
};
assert_eq!(result, test_payload);
assert_eq!(gas_left, U256::from(72_216));
assert_eq!(gas_left, U256::from(71_940));
}
// memmove test.
@ -509,7 +554,7 @@ fn memmove() {
};
assert_eq!(result, test_payload);
assert_eq!(gas_left, U256::from(72_216));
assert_eq!(gas_left, U256::from(71_940));
}
// memset test
@ -534,7 +579,7 @@ fn memset() {
};
assert_eq!(result, vec![228u8; 8192]);
assert_eq!(gas_left, U256::from(72_196));
assert_eq!(gas_left, U256::from(71_921));
}
macro_rules! reqrep_test {
@ -591,7 +636,7 @@ fn math_add() {
U256::from_dec_str("1888888888888888888888888888887").unwrap(),
(&result[..]).into()
);
assert_eq!(gas_left, U256::from(95_524));
assert_eq!(gas_left, U256::from(95_384));
}
// multiplication
@ -613,7 +658,7 @@ fn math_mul() {
U256::from_dec_str("888888888888888888888888888887111111111111111111111111111112").unwrap(),
(&result[..]).into()
);
assert_eq!(gas_left, U256::from(94_674));
assert_eq!(gas_left, U256::from(94_374));
}
// subtraction
@ -635,7 +680,7 @@ fn math_sub() {
U256::from_dec_str("111111111111111111111111111111").unwrap(),
(&result[..]).into()
);
assert_eq!(gas_left, U256::from(95_516));
assert_eq!(gas_left, U256::from(95_372));
}
// subtraction with overflow
@ -677,7 +722,7 @@ fn math_div() {
U256::from_dec_str("1125000").unwrap(),
(&result[..]).into()
);
assert_eq!(gas_left, U256::from(88_514));
assert_eq!(gas_left, U256::from(88_356));
}
// This test checks the ability of wasm contract to invoke
@ -765,7 +810,7 @@ fn externs() {
"Gas limit requested and returned does not match"
);
assert_eq!(gas_left, U256::from(94_858));
assert_eq!(gas_left, U256::from(95_321));
}
#[test]
@ -791,7 +836,7 @@ fn embedded_keccak() {
};
assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87"));
assert_eq!(gas_left, U256::from(81_446));
assert_eq!(gas_left, U256::from(81_067));
}
/// This test checks the correctness of log extern
@ -826,5 +871,5 @@ fn events() {
assert_eq!(&log_entry.data, b"gnihtemos");
assert_eq!(&result, b"gnihtemos");
assert_eq!(gas_left, U256::from(79_637));
assert_eq!(gas_left, U256::from(79_206));
}

View File

@ -174,7 +174,6 @@ pub mod aes {
}
/// ECDH functions
#[cfg_attr(feature="dev", allow(similar_names))]
pub mod ecdh {
use secp256k1::{ecdh, key, Error as SecpError};
use ethkey::{Secret, Public, SECP256K1};
@ -199,7 +198,6 @@ pub mod ecdh {
}
/// ECIES function
#[cfg_attr(feature="dev", allow(similar_names))]
pub mod ecies {
use rcrypto::digest::Digest;
use rcrypto::sha2::Sha256;

View File

@ -29,8 +29,6 @@ use presale::PresaleWallet;
use json::{self, Uuid, OpaqueKeyFile};
use {import, Error, SimpleSecretStore, SecretStore, SecretVaultRef, StoreAccountRef, Derivation, OpaqueSecret};
const REFRESH_TIME_SEC: u64 = 5;
/// Accounts store.
pub struct EthStore {
store: EthMultiStore,
@ -49,6 +47,16 @@ impl EthStore {
})
}
/// Modify account refresh timeout - how often they are re-read from `KeyDirectory`.
///
/// Setting this to low values (or 0) will cause new accounts to be picked up quickly,
/// although it may induce heavy disk reads and is not recommended if you manage many keys (say over 10k).
///
/// By default refreshing is disabled, so only accounts created using this instance of `EthStore` are taken into account.
pub fn set_refresh_time(&self, time: Duration) {
self.store.set_refresh_time(time)
}
fn get(&self, account: &StoreAccountRef) -> Result<SafeAccount, Error> {
let mut accounts = self.store.get_accounts(account)?.into_iter();
accounts.next().ok_or(Error::InvalidAccount)
@ -254,6 +262,7 @@ pub struct EthMultiStore {
struct Timestamp {
dir_hash: Option<u64>,
last_checked: Instant,
refresh_time: Duration,
}
impl EthMultiStore {
@ -272,16 +281,28 @@ impl EthMultiStore {
timestamp: Mutex::new(Timestamp {
dir_hash: None,
last_checked: Instant::now(),
// by default we never refresh accounts
refresh_time: Duration::from_secs(u64::max_value()),
}),
};
store.reload_accounts()?;
Ok(store)
}
/// Modify account refresh timeout - how often they are re-read from `KeyDirectory`.
///
/// Setting this to low values (or 0) will cause new accounts to be picked up quickly,
/// although it may induce heavy disk reads and is not recommended if you manage many keys (say over 10k).
///
/// By default refreshing is disabled, so only accounts created using this instance of `EthStore` are taken into account.
pub fn set_refresh_time(&self, time: Duration) {
self.timestamp.lock().refresh_time = time;
}
fn reload_if_changed(&self) -> Result<(), Error> {
let mut last_timestamp = self.timestamp.lock();
let now = Instant::now();
if (now - last_timestamp.last_checked) > Duration::from_secs(REFRESH_TIME_SEC) {
if now - last_timestamp.last_checked > last_timestamp.refresh_time {
let dir_hash = Some(self.dir.unique_repr()?);
last_timestamp.last_checked = now;
if last_timestamp.dir_hash == dir_hash {
@ -319,22 +340,23 @@ impl EthMultiStore {
}
fn get_accounts(&self, account: &StoreAccountRef) -> Result<Vec<SafeAccount>, Error> {
{
let from_cache = |account| {
let cache = self.cache.read();
if let Some(accounts) = cache.get(account) {
if !accounts.is_empty() {
return Ok(accounts.clone())
return Some(accounts.clone())
}
}
}
self.reload_if_changed()?;
let cache = self.cache.read();
let accounts = cache.get(account).ok_or(Error::InvalidAccount)?;
if accounts.is_empty() {
Err(Error::InvalidAccount)
} else {
Ok(accounts.clone())
None
};
match from_cache(account) {
Some(accounts) => Ok(accounts),
None => {
self.reload_if_changed()?;
from_cache(account).ok_or(Error::InvalidAccount)
}
}
}
@ -470,11 +492,20 @@ impl SimpleSecretStore for EthMultiStore {
}
fn account_ref(&self, address: &Address) -> Result<StoreAccountRef, Error> {
use std::collections::Bound;
self.reload_if_changed()?;
let cache = self.cache.read();
let mut r = cache.range((Bound::Included(*address), Bound::Included(*address)));
r.next().ok_or(Error::InvalidAccount).map(|(k, _)| k.clone())
let read_from_cache = |address: &Address| {
use std::collections::Bound;
let cache = self.cache.read();
let mut r = cache.range((Bound::Included(*address), Bound::Included(*address)));
r.next().map(|(k, _)| k.clone())
};
match read_from_cache(address) {
Some(account) => Ok(account),
None => {
self.reload_if_changed()?;
read_from_cache(address).ok_or(Error::InvalidAccount)
}
}
}
fn accounts(&self) -> Result<Vec<StoreAccountRef>, Error> {

View File

@ -150,6 +150,9 @@ impl<F: Fetch + 'static> HashFetch for Client<F> {
URLHintResult::Dapp(dapp) => {
dapp.url()
},
URLHintResult::GithubDapp(content) => {
content.url
},
URLHintResult::Content(content) => {
content.url
},

View File

@ -32,6 +32,10 @@ use bytes::Bytes;
pub type BoxFuture<A, B> = Box<Future<Item = A, Error = B> + Send>;
const COMMIT_LEN: usize = 20;
/// GithubHint entries with commit set as `0x0..01` should be treated
/// as Github Dapp, downloadable zip files, than can be extracted, containing
/// the manifest.json file along with the dapp
static GITHUB_DAPP_COMMIT: &[u8; COMMIT_LEN] = &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
/// RAW Contract interface.
/// Should execute transaction using current blockchain state.
@ -93,6 +97,8 @@ pub struct Content {
pub enum URLHintResult {
/// Dapp
Dapp(GithubApp),
/// GithubDapp
GithubDapp(Content),
/// Content
Content(Content),
}
@ -122,6 +128,15 @@ impl URLHintContract {
}
}
fn get_urlhint_content(account_slash_repo: String, owner: Address) -> Content {
let mime = guess_mime_type(&account_slash_repo).unwrap_or(mime::APPLICATION_JSON);
Content {
url: account_slash_repo,
mime,
owner,
}
}
fn decode_urlhint_output(output: (String, ::bigint::hash::H160, Address)) -> Option<URLHintResult> {
let (account_slash_repo, commit, owner) = output;
@ -130,13 +145,15 @@ fn decode_urlhint_output(output: (String, ::bigint::hash::H160, Address)) -> Opt
}
let commit = GithubApp::commit(&commit);
if commit == Some(Default::default()) {
let mime = guess_mime_type(&account_slash_repo).unwrap_or(mime::APPLICATION_JSON);
return Some(URLHintResult::Content(Content {
url: account_slash_repo,
mime: mime,
owner: owner,
}));
let content = get_urlhint_content(account_slash_repo, owner);
return Some(URLHintResult::Content(content));
}
if commit == Some(*GITHUB_DAPP_COMMIT) {
let content = get_urlhint_content(account_slash_repo, owner);
return Some(URLHintResult::GithubDapp(content));
}
let (account, repo) = {

View File

@ -15,9 +15,9 @@
}
},
"@parity/api": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@parity/api/-/api-2.1.5.tgz",
"integrity": "sha512-HkvMIhIwDMEIyTmXqEjWn1C2qes0qJO270bQldRfCZf0XiOGXG726EzV3FUpUbVONCVQ9riDviAl3fw6D+N6nA==",
"version": "2.1.14",
"resolved": "https://registry.npmjs.org/@parity/api/-/api-2.1.14.tgz",
"integrity": "sha512-1IiaXJCXkhNUNeWiMcLKrdXcPnLjdH58zIc8zk4IgwFvJ3ZNriV1W6lGHghHB9GbNcHgpZdpYt4NUvu67oWZ9w==",
"requires": {
"@parity/abi": "2.1.2",
"@parity/jsonrpc": "2.1.4",
@ -2165,7 +2165,6 @@
"version": "6.23.0",
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz",
"integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=",
"dev": true,
"requires": {
"core-js": "2.4.1",
"regenerator-runtime": "0.10.5"
@ -2174,8 +2173,7 @@
"regenerator-runtime": {
"version": "0.10.5",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz",
"integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=",
"dev": true
"integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg="
}
}
},
@ -3282,8 +3280,7 @@
"core-js": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz",
"integrity": "sha1-TekR5mew6ukSTjQlS1OupvxhjT4=",
"dev": true
"integrity": "sha1-TekR5mew6ukSTjQlS1OupvxhjT4="
},
"core-util-is": {
"version": "1.0.2",
@ -3419,11 +3416,6 @@
"randomfill": "1.0.3"
}
},
"crypto-js": {
"version": "3.1.8",
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.8.tgz",
"integrity": "sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU="
},
"css-color-names": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz",
@ -11017,24 +11009,8 @@
"react-inspector": {
"version": "github:paritytech/react-inspector#73b5214261a5131821eb9088f58d7e5f31210c23",
"requires": {
"babel-runtime": "6.26.0",
"babel-runtime": "6.23.0",
"is-dom": "1.0.9"
},
"dependencies": {
"babel-runtime": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
"requires": {
"core-js": "2.5.1",
"regenerator-runtime": "0.11.0"
}
},
"core-js": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz",
"integrity": "sha1-rmh03GaTd4m4B1T/VCjfZoGcpQs="
}
}
},
"react-intl": {
@ -13494,22 +13470,6 @@
}
}
},
"web3": {
"version": "0.17.0-beta",
"resolved": "https://registry.npmjs.org/web3/-/web3-0.17.0-beta.tgz",
"integrity": "sha1-V684JFv/ejIJn3zleA+tW7wA2ls=",
"requires": {
"bignumber.js": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2",
"crypto-js": "3.1.8",
"utf8": "2.1.2",
"xmlhttprequest": "1.8.0"
},
"dependencies": {
"bignumber.js": {
"version": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2"
}
}
},
"webidl-conversions": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
@ -13813,11 +13773,6 @@
"integrity": "sha1-TYuPHszTQZqjYgYb7O9RXh5VljU=",
"dev": true
},
"xmlhttprequest": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz",
"integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw="
},
"xss-filters": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/xss-filters/-/xss-filters-1.2.7.tgz",

View File

@ -31,7 +31,7 @@
"build:app": "webpack --config webpack/app",
"build:dll": "webpack --config webpack/vendor",
"ci:build": "cross-env NODE_ENV=production npm run build",
"clean": "rimraf ./.build ./.coverage ./.happypack ./.npmjs ./build ./node_modules/.cache",
"clean": "rimraf ./.build ./.coverage ./.happypack ./.npmjs ./node_modules/.cache",
"lint": "npm run lint:css && npm run lint:js",
"lint:css": "stylelint ./src/**/*.css",
"lint:js": "eslint --ignore-path .gitignore ./src/",
@ -133,7 +133,7 @@
},
"dependencies": {
"@parity/abi": "2.1.x",
"@parity/api": "2.1.x",
"@parity/api": "^2.1.14",
"@parity/wordlist": "1.1.x",
"base32.js": "0.1.0",
"bignumber.js": "3.0.1",
@ -203,7 +203,6 @@
"utf8": "2.1.2",
"valid-url": "1.0.9",
"validator": "6.2.0",
"web3": "0.17.0-beta",
"whatwg-fetch": "2.0.1",
"worker-loader": "^0.8.0",
"zxcvbn": "4.4.1"

View File

@ -1 +1 @@
// test script 21
// test script 22

View File

@ -33,7 +33,6 @@
<div id="container">
<div class="loading">Loading</div>
</div>
<script src="/parity-utils/inject.js"></script>
<script src="vendor.js"></script>
</body>
</html>

View File

@ -20,7 +20,6 @@
background-color: rgba(0, 0, 0, 0.8);
display: flex;
flex-direction: row;
height: 100%;
overflow: hidden;
transition: transform ease-out 0.1s;
transform: scale(1);

View File

@ -19,7 +19,7 @@ import { connect } from 'react-redux';
import { hashToImageUrl } from '~/redux/providers/imagesReducer';
import defaultIcon from '../../../assets/images/certifications/unknown.svg';
import defaultIcon from '~/../assets/images/certifications/unknown.svg';
import styles from './certifications.css';
@ -28,7 +28,6 @@ class Certifications extends Component {
address: PropTypes.string.isRequired,
certifications: PropTypes.array.isRequired,
className: PropTypes.string,
dappsUrl: PropTypes.string.isRequired,
showOnlyIcon: PropTypes.bool
}
@ -48,7 +47,7 @@ class Certifications extends Component {
renderCertification = (certification) => {
const { name, icon } = certification;
const { dappsUrl, showOnlyIcon } = this.props;
const { showOnlyIcon } = this.props;
const classNames = [
showOnlyIcon
@ -68,7 +67,7 @@ class Certifications extends Component {
className={ styles.icon }
src={
icon
? `${dappsUrl}${hashToImageUrl(icon)}`
? hashToImageUrl(icon)
: defaultIcon
}
/>

View File

@ -22,7 +22,8 @@ $transitionAll: all 0.75s cubic-bezier(0.23, 1, 0.32, 1);
.container {
background: $background;
flex: 1;
height: 100%;
/* Broke after Chrome upgrade, just commenting for now */
/* height: 100%; */
padding: 0em;
max-width: 100%;
position: relative;
@ -64,7 +65,8 @@ $transitionAll: all 0.75s cubic-bezier(0.23, 1, 0.32, 1);
.padded {
background-color: transparent !important;
border-radius: 0 !important;
height: 100%;
/* Broke after Chrome upgrade, just commenting for now */
/* height: 100%; */
position: relative;
overflow: auto;
}

View File

@ -105,9 +105,7 @@
}
.inputContainer {
display: flex;
flex-direction: column;
flex: 1;
justify-content: flex-start;
.input {
font-size: 1.5em;
@ -134,8 +132,6 @@
}
.category {
display: flex;
flex-direction: column;
margin: 0 0.5em;
max-width: 35em;
@ -149,12 +145,8 @@
}
.cards {
flex: 1;
overflow: auto;
display: flex;
flex-direction: column;
margin: 1em 0;
}

View File

@ -335,7 +335,7 @@ class AddressSelect extends Component {
content = (
<div className={ styles.cards }>
<div>{ cards }</div>
{ cards }
</div>
);
}

View File

@ -60,11 +60,10 @@ class IdentityIcon extends Component {
}
updateIcon (_address, images) {
const { api } = this.context;
const { button, inline, tiny } = this.props;
if (images[_address]) {
this.setState({ iconsrc: `${api.dappsUrl}${images[_address]}` });
this.setState({ iconsrc: images[_address] });
return;
}

View File

@ -80,7 +80,7 @@ describe('ui/IdentityIcon', () => {
const img = render({ address: ADDRESS2 }).find('img');
expect(img).to.have.length(1);
expect(img.props().src).to.equal('dappsUrl/reduxImage');
// expect(img.props().src).to.equal('dappsUrl/reduxImage');
});
it('renders an <ContractIcon> with no address specified', () => {

View File

@ -82,10 +82,9 @@ $popoverZ: 3600;
/* but may well be) will scretch to non-visible areas.
*/
&.small {
margin: 1.5em auto;
max-width: 768px;
position: relative;
width: 75%;
left: 50%;
margin: 1.5em -384px;
width: 768px;
}
}

View File

@ -19,7 +19,6 @@
cursor: pointer;
display: flex;
flex: 1;
height: 100%;
position: relative;
width: 100%;
@ -29,7 +28,6 @@
}
.content {
height: 100%;
width: 100%;
&:hover {

View File

@ -47,7 +47,6 @@
width: calc(.9em + 5px);
text-transform: initial;
vertical-align: bottom;
margin-top: -1em;
> .bar {
display: inline-block;

View File

@ -16,7 +16,9 @@
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { fetchTokens } from '~/redux/providers/tokensActions';
import unknownImage from '~/../assets/images/contracts/unknown-64x64.png';
class TokenImage extends Component {
@ -29,27 +31,39 @@ class TokenImage extends Component {
token: PropTypes.shape({
image: PropTypes.string,
address: PropTypes.string
}).isRequired
}).isRequired,
fetchTokens: PropTypes.func.isRequired
};
state = {
error: false
};
componentWillMount () {
const { token } = this.props;
if (token.native) {
return;
}
if (!token.fetched) {
if (!Number.isFinite(token.index)) {
return console.warn('no token index', token);
}
this.props.fetchTokens([ token.index ]);
}
}
render () {
const { error } = this.state;
const { api } = this.context;
const { image, token } = this.props;
const imageurl = token.image || image;
let imagesrc = unknownImage;
if (imageurl && !error) {
const host = /^(\/)?api/.test(imageurl)
? api.dappsUrl
: '';
imagesrc = `${host}${imageurl}`;
imagesrc = imageurl;
}
return (
@ -76,7 +90,13 @@ function mapStateToProps (iniState) {
};
}
function mapDispatchToProps (dispatch) {
return bindActionCreators({
fetchTokens
}, dispatch);
}
export default connect(
mapStateToProps,
null
mapDispatchToProps
)(TokenImage);

View File

@ -51,7 +51,7 @@ const defaultViews = {
},
contracts: {
active: false,
active: true,
onlyPersonal: true,
icon: <ContactsIcon />,
route: '/contracts',

1804
js/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "Parity",
"version": "1.9.22",
"version": "1.9.40",
"main": "src/index.parity.js",
"jsnext:main": "src/index.parity.js",
"author": "Parity Team <admin@parity.io>",
@ -27,7 +27,7 @@
"build:embed": "cross-env EMBED=1 node webpack/embed",
"build:i18n": "npm run clean && npm run build && babel-node ./scripts/build-i18n.js",
"ci:build": "cross-env NODE_ENV=production npm run build",
"clean": "rimraf ./.build ./.coverage ./.happypack ./build",
"clean": "rimraf ./.build ./.coverage ./.happypack",
"coveralls": "npm run testCoverage && coveralls < coverage/lcov.info",
"lint": "npm run lint:css && npm run lint:js",
"lint:cached": "npm run lint:css && npm run lint:js:cached",
@ -55,8 +55,6 @@
"@parity/dapp-signaturereg": "paritytech/dapp-signaturereg",
"@parity/dapp-tokendeploy": "paritytech/dapp-tokendeploy",
"@parity/dapp-tokenreg": "paritytech/dapp-tokenreg",
"@parity/dapp-vaults": "paritytech/dapp-vaults",
"@parity/dapp-web": "paritytech/dapp-web",
"babel-cli": "6.26.0",
"babel-core": "6.26.0",
"babel-eslint": "7.1.1",
@ -70,7 +68,7 @@
"babel-plugin-transform-runtime": "6.23.0",
"babel-plugin-webpack-alias": "2.1.2",
"babel-polyfill": "6.26.0",
"babel-preset-env": "1.6.0",
"babel-preset-env": "1.6.1",
"babel-preset-react": "6.24.1",
"babel-preset-stage-0": "6.24.1",
"babel-register": "6.26.0",
@ -142,14 +140,13 @@
"yargs": "6.6.0"
},
"dependencies": {
"@parity/api": "2.1.x",
"@parity/dapp-accounts": "paritytech/dapp-accounts",
"@parity/api": "^2.1.14",
"@parity/plugin-signer-account": "paritytech/plugin-signer-account",
"@parity/plugin-signer-default": "paritytech/plugin-signer-default",
"@parity/plugin-signer-hardware": "paritytech/plugin-signer-hardware",
"@parity/plugin-signer-qr": "paritytech/plugin-signer-qr",
"@parity/shared": "2.2.x",
"@parity/ui": "~3.0.4",
"@parity/shared": "2.2.14",
"@parity/ui": "3.0.20",
"keythereum": "1.0.2",
"lodash.flatten": "4.4.0",
"lodash.omitby": "4.6.0",
@ -173,6 +170,6 @@
"semantic-ui-react": "0.77.0",
"solc": "ngotchac/solc-js",
"store": "1.3.20",
"web3": "0.17.0-beta"
"web3": "1.0.0-beta.26"
}
}

View File

@ -1 +1 @@
// test script 26
// test script 27

View File

@ -19,39 +19,35 @@
box-sizing: border-box;
display: flex;
flex-direction: column;
min-height: 100vh;
height: 100vh;
width: 100%;
.logo {
top: 0;
right: 0;
left: 0;
bottom: 0;
opacity: 0.2;
position: fixed;
padding: 7em;
text-align: center;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
z-index: 0;
opacity: 0.2;
}
img {
display: inline-block;
margin: 0 auto;
.content {
box-sizing: border-box;
display: flex;
flex-grow: 1;
position: relative;
/* Show scrollbar for Homepage only, dapps' scrollbar are handled inside
* their iframe.
*/
& > div {
overflow-y: auto;
}
}
}
.container {
box-sizing: border-box;
display: flex;
flex-grow: 1;
flex-direction: column;
}
.content {
padding: 0;
}
.error {
padding: 2em;
background: red;
color: white;
.error {
padding: 2em;
background: red;
color: white;
}
}

View File

@ -36,7 +36,6 @@ import Status from '../Status';
import UpgradeParity from '../UpgradeParity';
import { appLogoDark as parityLogo } from '../config';
import Store from './store';
import styles from './application.css';
const inFrame = window.parent !== window && window.parent.frames.length !== 0;
@ -54,7 +53,6 @@ class Application extends Component {
pending: PropTypes.array
}
store = new Store(this.context.api);
hwstore = HardwareStore.get(this.context.api);
upgradeStore = UpgradeStore.get(this.context.api);
@ -77,6 +75,7 @@ class Application extends Component {
return (
<div className={ styles.application }>
<img src={ parityLogo } className={ styles.logo } />
{
blockNumber
? <Status upgradeStore={ this.upgradeStore } />
@ -109,35 +108,29 @@ class Application extends Component {
}
renderApp () {
const { children } = this.props;
return (
<div className={ styles.container }>
<Extension />
<FirstRun
onClose={ this.store.closeFirstrun }
visible={ this.store.firstrunVisible }
/>
<Snackbar />
<UpgradeParity upgradeStore={ this.upgradeStore } />
<Errors />
<div className={ styles.content }>
{ children }
</div>
</div>
);
return [
<Extension key='extension' />,
<FirstRun key='firstrun' />,
<Snackbar key='snackbar' />,
<UpgradeParity key='upgrade' upgradeStore={ this.upgradeStore } />,
<Errors key='errors' />,
this.renderContent()
];
}
renderMinimized () {
return [
<Errors key='errors' />,
this.renderContent()
];
}
renderContent () {
const { children } = this.props;
return (
<div className={ styles.container }>
<div className={ styles.logo }>
<img src={ parityLogo } />
</div>
<Errors />
{ children }
<div key='content' className={ styles.content }>
{children}
</div>
);
}

View File

@ -1,95 +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/>.
import { action, observable } from 'mobx';
import store from 'store';
const OLD_LS_FIRST_RUN_KEY = 'showFirstRun';
const LS_FIRST_RUN_KEY = '_parity::showFirstRun';
export default class Store {
@observable firstrunVisible = false;
constructor (api) {
// Migrate the old key to the new one
this._migrateStore();
this._api = api;
// Show the first run the storage doesn't hold `false` value
const firstrunVisible = store.get(LS_FIRST_RUN_KEY) !== false;
// Only check accounts if we might show the first run
if (firstrunVisible) {
api.transport.once('open', () => {
this._checkAccounts();
});
} else {
this.firstrunVisible = false;
}
}
@action closeFirstrun = () => {
this.toggleFirstrun(false);
}
@action toggleFirstrun = (visible = false) => {
this.firstrunVisible = visible;
// There's no need to write to storage that the
// First Run should be visible
if (!visible) {
store.set(LS_FIRST_RUN_KEY, !!visible);
}
}
/**
* Migrate the old LocalStorage key format
* to the new one
*/
_migrateStore () {
const oldValue = store.get(OLD_LS_FIRST_RUN_KEY);
const newValue = store.get(LS_FIRST_RUN_KEY);
if (newValue === undefined && oldValue !== undefined) {
store.set(LS_FIRST_RUN_KEY, oldValue);
store.remove(OLD_LS_FIRST_RUN_KEY);
}
}
_checkAccounts () {
return Promise
.all([
this._api.parity.listVaults(),
this._api.parity.allAccountsInfo()
])
.then(([ vaults, info ]) => {
const accounts = Object.keys(info)
.filter((address) => info[address].uuid)
// In DEV mode, the empty phrase account is already added
.filter((address) => address.toLowerCase() !== '0x00a329c0648769a73afac7f9381e08fb43dbea72');
// Has accounts if any vaults or accounts
const hasAccounts = (accounts && accounts.length > 0) || (vaults && vaults.length > 0);
// Show First Run if no accounts and no vaults
this.toggleFirstrun(!hasAccounts);
})
.catch((error) => {
console.error('checkAccounts', error);
});
}
}

View File

@ -53,9 +53,9 @@
}
.form {
margin-top: 0.75em;
margin-top: 1em;
padding: 0 4em;
text-align: left;
text-align: center;
}
.timestamp {
@ -71,14 +71,15 @@
}
.icons {
padding-top: 1.5em;
margin-top: 2em;
margin-bottom: 0;
}
.icon,
.iconSmall {
display: inline-block;
padding: 1em;
padding-bottom: 1em;
margin-top: 2em;
padding: 0 1.5em;
vertical-align: middle;
}
@ -92,10 +93,13 @@
}
.console {
width: 80%;
font-family: 'Roboto Mono', monospace;
background: rgba(0, 0, 0, 0.25);
background: rgba(0, 0, 0, 0.65);
font-size: 16px;
padding: 0 0.25em;
padding: 0.5em 0.25em;
margin: 1em auto;
border-radius: 3px;
}
@keyframes pulse {
@ -123,10 +127,11 @@
color: rgb(208, 208, 208);
}
.formInput input {
.formInput input[type=text] {
background: rgba(0, 0, 0, 0.25) !important;
text-align: center;
}
.formInput input:focus {
.formInput input[type=text]:focus {
background: rgba(0, 0, 0, 0.25) !important;
}

View File

@ -21,7 +21,7 @@ import PropTypes from 'prop-types';
import GradientBg from '@parity/ui/lib/GradientBg';
import Input from '@parity/ui/lib/Form/Input';
import { CompareIcon, ComputerIcon, DashboardIcon, VpnIcon } from '@parity/ui/lib/Icons';
import { CompareIcon, ComputerIcon, DashboardIcon, KeyIcon } from '@parity/ui/lib/Icons';
import styles from './connection.css';
@ -64,7 +64,7 @@ class Connection extends Component {
<div className={ styles.icon }>
{
needsToken
? <VpnIcon className={ styles.svg } />
? <KeyIcon className={ styles.svg } />
: <DashboardIcon className={ styles.svg } />
}
</div>
@ -90,18 +90,12 @@ class Connection extends Component {
<div>
<FormattedMessage
id='connection.noConnection'
defaultMessage='Unable to make a connection to the Parity Secure API. To update your secure token or to generate a new one, run: {newToken} and paste the generated token into the space below.'
defaultMessage='To proceed you need to generate a new security token by running the following command in your terminal {newToken} Then copy &amp; paste the newly generated token here'
values={ {
newToken: <div className={ styles.console }>parity signer new-token</div>
newToken: <div className={ styles.console }>$ parity signer new-token</div>
} }
/>
</div>
<div className={ styles.timestamp }>
<FormattedMessage
id='connection.timestamp'
defaultMessage='Ensure that both the Parity node and this machine connecting have computer clocks in-sync with each other and with a timestamp server, ensuring both successful token validation and block operations.'
/>
</div>
<div className={ styles.form }>
<Input
className={ styles.formInput }
@ -120,7 +114,7 @@ class Connection extends Component {
hint={
<FormattedMessage
id='connection.token.hint'
defaultMessage='Insert the generated token here'
defaultMessage='xxXX-Xxxx-xXxx-XxXX'
/>
}
onChange={ this.onChangeToken }

View File

@ -15,22 +15,20 @@
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
*/
.frame {
.frame,
.full {
background: white;
box-sizing: border-box;
border: 0;
flex-grow: 1;
margin: 0;
padding: 0;
opacity: 0;
width: 100%;
z-index: 1;
}
.full {
width: 100vw;
height: 100vh;
margin: 0;
padding: 0;
background: white;
font-family: 'Roboto', sans-serif;
font-size: 16px;
font-weight: 300;

View File

@ -19,7 +19,6 @@ import { observer } from 'mobx-react';
import { FormattedMessage } from 'react-intl';
import PropTypes from 'prop-types';
import Api from '@parity/api';
import builtinDapps from '@parity/shared/lib/config/dappsBuiltin.json';
import viewsDapps from '@parity/shared/lib/config/dappsViews.json';
import DappsStore from '@parity/shared/lib/mobx/dappsStore';
@ -27,15 +26,7 @@ import HistoryStore from '@parity/shared/lib/mobx/historyStore';
import styles from './dapp.css';
const internalDapps = []
.concat(viewsDapps, builtinDapps)
.map((app) => {
if (app.id && app.id.substr(0, 2) !== '0x') {
app.id = Api.util.sha3(app.id);
}
return app;
});
const internalDapps = [].concat(viewsDapps, builtinDapps);
@observer
export default class Dapp extends Component {
@ -130,13 +121,9 @@ export default class Dapp extends Component {
dapphost = '';
}
const appId = this.context.api.util.isHex(app.id)
? app.id
: this.context.api.sha3(app.url);
src = window.location.protocol === 'file:'
? `dapps/${appId}/index.html`
: `${dapphost}/dapps/${appId}/index.html`;
? `dapps/${app.id}/index.html`
: `${dapphost}/dapps/${app.id}/index.html`;
break;
}

View File

@ -6,4 +6,16 @@ To be clear with the terminology used in the code here:
- a *methodGroup* is the grouping of similar methods (see `methodGroups.js`)
- a *permission* is a boolean which tells if an app is allowed to call a method or not
- a *request* is when an app prompts the shell to call a method
- a *requestGroup* is an array of *requests* whose methods are in the same *methodGroup*
- a *requestGroup* is a map of the following form
```javascript
{
appId1: {
methodGroup1: [request1, request2] // This is a requestGroup sub-item
},
appId2: {
methodGroup1: [request1]
methodGroup2: [request3]
},
// ...
}
```

View File

@ -0,0 +1,24 @@
/* 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/>.
*/
.requestGroupSubItem {
margin-top: 2px;
.requestGroupSubItemTitle {
margin-right: 10px;
}
}

View File

@ -0,0 +1,76 @@
// 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/>.
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import Popup from 'semantic-ui-react/dist/commonjs/modules/Popup';
import Button from '@parity/ui/lib/Button';
import methodGroups from '../../methodGroups';
import styles from './RequestGroupSubItem.css';
export default class RequestGroupSubItem extends PureComponent {
handleApprove = () => this.props.onApprove(this.props.requests, this.props.groupId)
handleReject = () => this.props.onReject(this.props.requests)
render () {
const { groupId } = this.props;
return (
<div className={ styles.requestGroupSubItem }>
<span className={ styles.requestGroupSubItemTitle }>
Permission for{' '}
<Popup
trigger={ <span>{groupId}</span> }
content={ `Requested methods: ${methodGroups[groupId].methods.join(', ')}` }
/>
</span>
<Button
size='mini'
label={
<FormattedMessage
id='dappRequests.request.buttons.approve'
defaultMessage='Approve'
/>
}
onClick={ this.handleApprove }
/>
<Button
size='mini'
label={
<FormattedMessage
id='dappRequests.request.buttons.reject'
defaultMessage='Reject'
/>
}
onClick={ this.handleReject }
/>
</div>
);
}
}
RequestGroupSubItem.propTypes = {
className: PropTypes.string,
groupId: PropTypes.string,
onApprove: PropTypes.func.isRequired,
onReject: PropTypes.func.isRequired,
requests: PropTypes.array.isRequired
};

View File

@ -0,0 +1,17 @@
// 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/>.
export default from './RequestGroupSubItem';

View File

@ -28,12 +28,4 @@ $backgroundTwo: #e57a00;
> span {
margin-right: 30px;
}
.requestGroup {
margin-top: 2px;
.requestGroupTitle {
margin-right: 10px;
}
}
}

View File

@ -14,49 +14,25 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import React, { PureComponent } from 'react';
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import Popup from 'semantic-ui-react/dist/commonjs/modules/Popup';
import Button from '@parity/ui/lib/Button';
import DappsStore from '@parity/shared/lib/mobx/dappsStore';
import RequestGroupSubItem from './RequestGroupSubItem';
import styles from './RequestGroups.css';
export default class RequestGroups extends PureComponent {
state = {
opened: false
};
handleApproveRequestGroup = groupId => {
const { requestGroups, onApproveRequestGroup } = this.props;
onApproveRequestGroup(Object.values(requestGroups[groupId].map(({ requestId }) => requestId)));
}
handleRejectRequestGroup = groupId => {
const { requestGroups, onRejectRequestGroup } = this.props;
onRejectRequestGroup(Object.values(requestGroups[groupId].map(({ requestId }) => requestId)));
}
renderPopupContent = groupId => {
const { requestGroups } = this.props;
// Get unique list of methods in that request group
const requestedMethods = [...new Set(
Object.values(requestGroups[groupId])
.map(request => request.data.method || request.data.params[0])
)];
return `Requested methods: ${requestedMethods.join(', ')}`;
export default class RequestGroups extends Component {
handleApproveRequestGroup = (requests, groupId) => {
this.props.onApproveRequestGroup(requests, groupId, this.props.appId);
}
render () {
const {
appId,
requestGroups
requestGroups,
onRejectRequestGroup
} = this.props;
const app = DappsStore.get().getAppById(appId);
@ -72,35 +48,13 @@ export default class RequestGroups extends PureComponent {
} }
/>
{Object.keys(requestGroups).map(groupId => (
<div key={ `${appId}-${groupId}` } className={ styles.requestGroup }>
<span className={ styles.requestGroupTitle }>
Permission for{' '}
<Popup
trigger={ <span>{groupId}</span> }
content={ this.renderPopupContent(groupId) }
/>
</span>
<Button
size='mini'
label={
<FormattedMessage
id='dappRequests.request.buttons.approve'
defaultMessage='Approve'
/>
}
onClick={ () => this.handleApproveRequestGroup(groupId) }
/>
<Button
size='mini'
label={
<FormattedMessage
id='dappRequests.request.buttons.reject'
defaultMessage='Reject'
/>
}
onClick={ () => this.handleRejectRequestGroup(groupId) }
/>
</div>
<RequestGroupSubItem
key={ `${appId}-${groupId}` }
groupId={ groupId }
requests={ requestGroups[groupId] }
onApprove={ this.handleApproveRequestGroup }
onReject={ onRejectRequestGroup }
/>
))}
</div>
);

View File

@ -17,6 +17,7 @@
import { observer } from 'mobx-react';
import React, { Component } from 'react';
import methodGroups from './methodGroups';
import RequestGroups from './RequestGroups';
import Store from './store';
import styles from './dappRequests.css';
@ -24,12 +25,16 @@ import styles from './dappRequests.css';
class DappRequests extends Component {
store = Store.get();
handleApproveRequestGroup = requestIds => {
requestIds.forEach(this.store.approveRequest);
// When we approve a requestGroup, when approve all the requests, and add permissions
// to all the other methods in the same methodGroup
handleApproveRequestGroup = (requests, groupId, appId) => {
requests.map(({ requestId }) => requestId).forEach(this.store.approveRequest);
methodGroups[groupId].methods.forEach(method => this.store.addAppPermission(method, appId));
}
handleRejectRequestGroup = requestIds => {
requestIds.forEach(this.store.rejectRequest);
// When we reject a requestGroup, we reject the requests in that group
handleRejectRequestGroup = requests => {
requests.map(({ requestId }) => requestId).forEach(this.store.rejectRequest);
}
render () {

View File

@ -17,16 +17,33 @@
const methodGroups = {
shell: {
methods: [
'shell_loadApp'
]
},
dapps: {
methods: [
'parity_dappsRefresh',
'parity_dappsUrl',
'shell_getApps',
'shell_getFilteredMethods',
'shell_getMethodGroups',
'shell_getMethodPermissions',
'shell_getMethodPermissions'
]
},
dappsEdit: {
methods: [
'shell_setAppPinned',
'shell_setAppVisibility',
'shell_setMethodPermissions'
]
},
accountsView: {
methods: ['parity_accountsInfo', 'parity_allAccountsInfo']
accounts: {
methods: [
'parity_accountsInfo',
'parity_allAccountsInfo',
'parity_getNewDappsAddresses',
'parity_getNewDappsDefaultAddress',
'parity_hardwareAccountsInfo',
'parity_lockedHardwareAccountsInfo'
]
},
accountsCreate: {
methods: [
@ -40,35 +57,67 @@ const methodGroups = {
]
},
accountsEdit: {
methods: ['parity_setAccountName', 'parity_setAccountMeta']
},
upgrade: {
methods: [
'parity_consensusCapability',
'parity_executeUpgrade',
'parity_upgradeReady',
'parity_versionInfo'
'parity_setAccountName',
'parity_setAccountMeta',
'parity_hardwarePinMatrixAck',
'parity_setNewDappsAddresses',
'parity_setNewDappsDefaultAddress'
]
},
accountsDelete: {
methods: [
'parity_killAccount',
'parity_removeAddress'
]
},
vaults: {
methods: [
'parity_changeVault',
'parity_changeVaultPassword',
'parity_closeVault',
'parity_getVaultMeta',
'parity_listVaults',
'parity_listOpenedVaults',
'parity_newVault',
'parity_openVault',
'parity_openVault'
]
},
vaultsCreate: {
methods: [
'parity_newVault'
]
},
vaultsEdit: {
methods: [
'parity_changeVault',
'parity_changeVaultPassword',
'parity_setVaultMeta'
]
},
other: {
signerRequests: {
methods: [
'parity_checkRequest',
'parity_hashContent',
'parity_localTransactions'
]
},
signerConfirm: {
methods: [
'parity_confirmRequest',
'parity_confirmRequestRaw',
'parity_rejectRequest'
]
},
node: {
methods: [
'parity_hashContent',
'parity_consensusCapability',
'parity_upgradeReady',
'parity_versionInfo',
'parity_wsUrl'
]
},
nodeUpgrade: {
methods: [
'parity_executeUpgrade'
]
}
};

View File

@ -52,7 +52,7 @@ export default class Store {
accumulator[appId] = accumulator[appId] || {};
accumulator[appId][methodGroup] = accumulator[appId][methodGroup] || [];
accumulator[appId][methodGroup].push({ data, requestId }); // Append the requestId field in the request object
accumulator[appId][methodGroup].push({ data, requestId }); // Push request & append the requestId field in the request object
return accumulator;
}, {});
@ -99,7 +99,7 @@ export default class Store {
this.requests = { ...this.requests };
};
getPermissionId = (method, appId) => `${method}:${appId}` // Create an id to identify permissions based on method and appId
getPermissionId = (method, appId) => `${method}:${appId}`; // Create an id to identify permissions based on method and appId
getMethodFromRequest = requestId => {
const { data: { method, params } } = this.requests[requestId];
@ -131,13 +131,10 @@ export default class Store {
};
setPermissions = _permissions => {
const permissions = {};
Object.keys(_permissions).forEach(id => {
permissions[id] = !!_permissions[id];
});
this.permissions = permissions;
this.permissions = {
...this.permissions,
..._permissions
};
this.savePermissions();
return true;
@ -245,14 +242,9 @@ export default class Store {
return;
}
if (
(method &&
methodGroupFromMethod[method] &&
!this.hasTokenPermission(method, token)) ||
(api &&
methodGroupFromMethod[params[0]] &&
!this.hasTokenPermission(method, token))
) {
const _method = api ? params[0] : method;
if (methodGroupFromMethod[_method] && !this.hasTokenPermission(_method, token)) {
this.queueRequest(id, { // The requestId of a request is the id inside data
data,
source

View File

@ -0,0 +1,54 @@
/* 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/>.
*/
.card {
position: relative;
margin-top: 3em;
.pin {
display: none;
position: absolute;
top: 0;
right: 1.6em;
z-index: 1;
}
.pin.pinned {
display: block;
transform: rotate(45deg);
}
&:hover {
.pin {
display: block;
}
}
.content {
display: block;
padding-top: 1em;
.title {
margin-top: 0.8em;
}
.image {
margin-left: auto;
margin-right: auto;
}
}
}

View File

@ -0,0 +1,72 @@
// 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/>.
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router';
import DappIcon from '@parity/ui/lib/DappIcon';
import Header from 'semantic-ui-react/dist/commonjs/elements/Header';
import Button from 'semantic-ui-react/dist/commonjs/elements/Button';
import styles from './dappCard.css';
export default class DappCard extends Component {
static propTypes = {
app: PropTypes.object.isRequired,
availability: PropTypes.string.isRequired,
className: PropTypes.string,
onPin: PropTypes.func,
pinned: PropTypes.bool
};
handlePin = () => this.props.onPin(this.props.app.id)
render () {
const { app, availability, className, pinned } = this.props;
if (app.onlyPersonal && availability !== 'personal') {
return null;
}
return (
<div className={ [styles.card, className].join(' ') }>
<Button
size='mini'
icon='pin'
circular
className={ [styles.pin, pinned && styles.pinned].join(' ') }
onClick={ this.handlePin }
/>
<div className={ styles.content }>
<Link to={ app.url === 'web' ? '/web' : `/${app.id}` } >
<DappIcon
app={ app }
className={ styles.image }
/>
<Header
as='h5'
textAlign='center'
className={ styles.title }
>
{app.name}
</Header>
</Link>
</div>
</div>
);
}
}

View File

@ -0,0 +1,17 @@
// 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/>.
export default from './dappCard';

View File

@ -16,13 +16,46 @@
*/
.overlay {
background: rgba(40, 40, 40, 0.85);
color: white;
line-height: 1.5em;
margin: 0 auto;
text-align: left;
max-width: 980px;
padding: 4em 2em;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
text-align: center;
z-index: 100;
& > div:first-child {
padding-bottom: 1em;
div {
max-width: 640px;
margin: 1em auto;
text-align: left;
}
.accept {
label {
color: white;
}
}
}
.sectionTitle {
padding: 2em 0 0 4em !important;
margin-bottom: 0 !important;
}
.dapps {
padding: 0 1.5em;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
.dapp {
width: 12em;
margin-left: 2em;
margin-right: 2em;
}
}

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